I'm trying to make a waiting screen using Form Glass Pane in LWUIT, the following is the code that I'm using
public class LoadingGlassPane implements Painter {
public static boolean isShown = false;
public static IForm form;
public void paint(Graphics g, Rectangle rect) {
System.out.println("paint LoadingGlassPane");
Font font = g.getFont();
int color = g.getColor();
g.setColor(0);
g.setFont(Font.getDefaultFont());
g.drawString("Loading...", 20, 120);
g.setColor(color);
g.setFont(font);
}
public void installPane(IForm f) {
f.setGlassPane(this);
}
public void uninstallPane(IForm f) {
f.setGlassPane(null);
}
public static IForm getForm() {
return form;
}
public static void setForm(IForm form) {
LoadingGlassPane.form = form;
}
public static boolean isIsShown() {
return isShown;
}
public static void setIsShown(boolean isShown) {
LoadingGlassPane.isShown = isShown;
}
}
and
public class ProgressGlassPane extends LoadingGlassPane implements Animation, Runnable {
int spacing = 20;
int fontSpacing = 10;
String loadMsg = "Loading...";
//HTMLComponent htmlC;
// Dialog loading;
// public ProgressGlassPane(Dialog loading) {
// this.loading = loading;
// }
public ProgressGlassPane() {
}
public void paint(Graphics g, Rectangle rect) {
//while (isShown == true) {
System.out.println("paint ProgressGlassPane");
int color = g.getColor();
Font font = g.getFont();
int pos = (int) ((System.currentTimeMillis() % 2700) / 300);
Font f = Font.getDefaultFont();
//int startX = loading.getAbsoluteX() + (loading.getWidth() / 2) - spacing;
int startX = (LGB.width / 2) - spacing;
//int fontStartX = loading.getAbsoluteX() + (loading.getWidth() - f.stringWidth(loadMsg)) / 2;
int fontStartX = (LGB.width - f.stringWidth(loadMsg)) / 2;
//int startY = loading.getAbsoluteY() + (loading.getHeight() / 2) - spacing - (f.getHeight() + fontSpacing) / 2;
int startY = (LGB.height / 2) - spacing - (f.getHeight() + fontSpacing) / 2;
int i = 0;
g.setColor(0xffffff);
g.fillRect(Math.min(startX - 3, fontStartX), startY - 3, Math.max(spacing * 2 + 7, f.stringWidth(loadMsg)) + 1, spacing * 2 + 7 + f.getHeight() + fontSpacing);
g.setColor(0);
g.setFont(f);
g.drawString(loadMsg, fontStartX, startY);
startY += f.getHeight() + fontSpacing;
for (int y = 0; y < 3; y++) {
for (int x = 0; x < 3; x++) {
int thickness = 3;
if (i == pos) {
thickness = 7;
} else if (i == pos - 1) {
thickness = 5;
}
g.fillRect(startX + x * spacing - (thickness / 2), startY + y * spacing - (thickness / 2), thickness, thickness);
i++;
}
}
g.setColor(color);
g.setFont(font);
// }
}
public boolean animate() {
return true;
}
public void paint(Graphics g) {
paint(g, null);
}
//void installPane(Form f) {
public void installPane(IForm f) {
super.installPane(f);
//f.setGlassPane(this);
f.registerAnimated(this);
}
//void uninstallPane(Form f) {
public void uninstallPane(IForm f) {
super.uninstallPane(f);
//f.setGlassPane(this);
f.deregisterAnimated(this);
}
public void run() {
System.out.println("I'm running");
if (isShown == true && form != null) {
installPane(form);
}
else
{
uninstallPane(form);
}
}
}
and from within my form
public static ProgressGlassPane progressPane;
progressPane = new ProgressGlassPane();
progressPane.setForm(this);
progressPane.setIsShown(true);
progressPane.run();
//Some Webservice code I want to run
progressPane.setIsShown(false);
What I want to do exactly is to open the glass pan while I'm loading my data and hide it when I finish, but what Happen it send the request and after get the response show the glass pane , I have tried to put my glass pane in different thread to run independently from the main thread, and it is also not working.
Is the webservice code blocking?
If you are on the EDT then that just wouldn't work. You need to uninstall from the completion.
Related
I generate a matrix about my game map by random Prim. Then I draw the map by menuItem in the cocos2d-x 4.0. I want to control a sprite to move by key "asdw". But I cannot control the sprite to cross the bamboo walls. Sometimes the sprite is surrounded by bamboo walls.
How can I check the wall? How can I ensure a path that the sprite can move to the destination?
This is my result image
cross the wall
sprite is surrounded
My code is below.
MazeScene.h
#pragma once
#ifndef __Maze_SCENE_H__
#define __Maze_SCENE_H__
#endif // __SECOND_SCENE_H__
#include "cocos2d.h"
#include<vector>
#include <time.h>
#define m 18 //row
#define n 10 //columns
#define down 1
#define right 2
#define left 4
#define up 8
#define WALL -1
#define NOTHING 2
USING_NS_CC;
class MazeScene : public cocos2d::Layer {
public:
Sprite* sprite;
int backgroundAudioID;
static cocos2d::Scene* createScene();
virtual bool init();
void initMap();
void onReset();
void changeScene(float dt);
void update(float dt);
void GameOver();
void Success();
void onKeyPressed(EventKeyboard::KeyCode keyCode, Event* event);
void FindBlock();
CREATE_FUNC(MazeScene);
private:
struct block {
int row, column, direction;
block(int _row, int _column, int _direction) {
row = _row;
column = _column;
direction = _direction;
}
};
struct point {
int x;
int y;
}start, end;
std::vector<block> myblock;
int x_num = 1, y_num = 1;//Miner location
int G[100][100];
Sprite* _player;
Sprite* _door;
Menu* mazeMenu;
int life = 180;
int i = 0;
};
MazeScene.cpp
#include "MazeScene.h"
#include <AudioEngine.h>
#include <MenuScene.h>
USING_NS_CC;
using namespace std;
#define UserDefault UserDefault::getInstance()
cocos2d::Scene* MazeScene::createScene()
{
auto scene = Scene::create();
auto layer = MazeScene::create();
scene->addChild(layer);
return scene;
}
bool MazeScene::init()
{
if (!Layer::init())
{
return false;
}
AudioEngine::play2d("music/leisure.mp3",true);
// special effect
auto particleSystem = ParticleSystemQuad::create("image/mist.plist");
particleSystem->setPosition(1500, 500);
this->addChild(particleSystem, 1);
auto particleSystem1 = ParticleSystemQuad::create("image/mist2.plist");
particleSystem1->setPosition(-500, 400);
this->addChild(particleSystem1, 1);
this->schedule(CC_SCHEDULE_SELECTOR(MazeScene::update), 1.0);
initMap();
return true;
}
void MazeScene::initMap() {
//Put all the map as a wall
memset(G, WALL, sizeof(G));
//Define the starting point
G[1][1] = NOTHING;
start.x = start.y = 1;
srand((unsigned)time(NULL));//Random number seed
FindBlock();
//The first step is to press into the two walls (to the right of the starting point and
below the starting point) to enter the loop
while (myblock.size()) {
int BlockSize = myblock.size();
//Randomly select a wall (generate a random number between 0 and BlockSize-1, which
is also the subscript of the wall in the vector)
int randnum = rand() % BlockSize;
block SelectBlock = myblock[randnum];
x_num = SelectBlock.row;//Miners come to our "wall of choice" here
y_num = SelectBlock.column;
//Follow-up operations based on the direction of the currently selected wall
//At this time, the three areas of the wall and target block selected as the
starting point are on the same straight line.
//We let the miners move on from the "wall of choice" to the "target block"
//Miners have the ability to penetrate walls :)
switch (SelectBlock.direction) {
case down: {
x_num++;
break;
}
case right: {
y_num++;
break;
}
case left: {
y_num--;
break;
}
case up: {
x_num--;
break;
}
}
//If the target block is a wall
if (G[x_num][y_num] == WALL) {
//Break through the wall and target block
G[SelectBlock.row][SelectBlock.column] = G[x_num][y_num] = NOTHING;
//Find again the wall adjacent to the current location of the miner
FindBlock();
}
else {//If not? It means that our miners have dug into an empty path and just take a
rest.
//relax
}
//Delete this wall (delete the unusable wall, for those who have already been
constructed, there is no need to construct it, but also to ensure that we can jump
out of the loop)
myblock.erase(myblock.begin() + randnum);
}
Vector<MenuItem*> spriteBtns;
std::string imgName;
for (int i = 0; i <= m + 1; i++) {
for (int j = 0; j <= n + 1; j++) {
if (i == start.x && j == start.y) {
imgName = "general.png";
}else if(G[i][j] == NOTHING) {
imgName = "nud.png";
}
else if(i == m + 1 && j == n + 1) {
imgName = "image/evidence.png";
}
else {
imgName = "bamboo.png";
}
auto btnSprite = MenuItemImage::create(imgName,imgName);
Size cts = btnSprite->getContentSize();
btnSprite->setPosition(i*cts.width,j*cts.height);
spriteBtns.pushBack(btnSprite);
}
}
mazeMenu = Menu::createWithArray(spriteBtns);
addChild(mazeMenu);
mazeMenu->setPosition(30,80);
_player = Sprite::create("general.png");
_player->setPosition(90, 130);
this->addChild(_player);
_door = Sprite::create("image/evidence.png");
_door->setPosition(900,630);
this->addChild(_door);
// Keyboard event monitoring
auto keyListener = EventListenerKeyboard::create();
keyListener->onKeyPressed = CC_CALLBACK_2(MazeScene::onKeyPressed, this);
_eventDispatcher->addEventListenerWithSceneGraphPriority(keyListener, this);
}
void MazeScene::onReset() {
initMap();
}
void MazeScene::changeScene(float dt) {
Director::getInstance()->replaceScene(TransitionSlideInT::create(3.0f,
MenuScene::createScene()));
}
void MazeScene::update(float dt) {
life--;
if (_player->getBoundingBox().intersectsRect(_door->getBoundingBox())) {
initMap();
i++;
}
if (life<=0) {
GameOver();
this->scheduleOnce(CC_SCHEDULE_SELECTOR(MazeScene::changeScene), 5.0);
}
if (i == 3 && life > 0) {
UserDefault->setIntegerForKey("step4", 4);
UserDefault->flush();
Success();
this->scheduleOnce(CC_SCHEDULE_SELECTOR(MazeScene::changeScene), 5.0);
}
}
void MazeScene::GameOver() {
this->unscheduleAllCallbacks();
AudioEngine::play2d("music/over.mp3", false, 0.3);
AudioEngine::stopAll();
auto sprite = Sprite::create("image/over2.png");
auto visibleSize = Director::getInstance()->getVisibleSize();
Vec2 origin = Director::getInstance()->getVisibleOrigin();
sprite->setPosition(Vec2(visibleSize.width / 2 + origin.x, visibleSize.height / 2 +
origin.y));
this->addChild(sprite, 10);
}
void MazeScene::Success() {
this->unscheduleAllCallbacks();
AudioEngine::play2d("music/victory.mp3", false, 0.3);
AudioEngine::stopAll();
auto sprite = Sprite::create("image/success2.png");
auto visibleSize = Director::getInstance()->getVisibleSize();
Vec2 origin = Director::getInstance()->getVisibleOrigin();
sprite->setPosition(Vec2(visibleSize.width / 2 + origin.x, visibleSize.height / 2 +
origin.y));
this->addChild(sprite, 10);
}
void MazeScene::onKeyPressed(EventKeyboard::KeyCode keyCode, Event* event) {
log("Key with keycode %d pressed", keyCode);
switch (keyCode) {
case EventKeyboard::KeyCode::KEY_D:
{
auto moveBy = MoveBy::create(0.5f, Vec2(25, 0));
_player->runAction(Sequence::create(moveBy, nullptr));
break;
}
case EventKeyboard::KeyCode::KEY_A:
{
auto moveBy = MoveBy::create(0.5f, Vec2(-25, 0));
_player->runAction(Sequence::create(moveBy, nullptr));
break;
}
case EventKeyboard::KeyCode::KEY_W:
{
auto moveBy = MoveBy::create(0.5f, Vec2(0, 25));
_player->runAction(Sequence::create(moveBy, nullptr));
break;
}
case EventKeyboard::KeyCode::KEY_S:
{
auto moveBy = MoveBy::create(0.5f, Vec2(0, -25));
_player->runAction(Sequence::create(moveBy, nullptr));
break;
}
default:
break;
}
}
void MazeScene::FindBlock() {
//find Find nearby walls
if (x_num + 1 <= m && G[x_num + 1][y_num] == WALL) {//down
myblock.push_back(block(x_num + 1, y_num, down));
}
if (y_num + 1 <= n && G[x_num][y_num + 1] == WALL) {//right
myblock.push_back(block(x_num, y_num + 1, right));
}
if (x_num - 1 >= 1 && G[x_num - 1][y_num] == WALL) {//up
myblock.push_back(block(x_num - 1, y_num, up));
}
if (y_num - 1 >= 1 && G[x_num][y_num - 1] == WALL) {//left
myblock.push_back(block(x_num, y_num - 1, left));
}
}
As a school project, I've made the classic snake game using SDL2 and C++.
I've already implemented the growing, moving features for the Snake but it was required to make the movement based on a grid, but when I implemented the grid feature, the self-collision was always triggering whenever grow one part, so every time I start the game, and eat the first fruit, the snake dies.
I've been trying for a while now, from placing a delay to the adding of the tail and delaying the collision check, but to no avail, it's always colliding with itself even though it is not.
I can't see what is wrong with the self collision, I would gladly appreciate it if someone can point out what's wrong.
Snake.h
#include "GameObject.h"
#include "common.h"
#include "draw.h"
#include "Food.h"
#include "util.h"
#include <vector>
struct Segment {
int x;
int y;
Segment(int posx, int posy) {
x = posx;
y = posy;
}
};
class Snake :
public GameObject
{
public:
~Snake();
void start();
void update();
void draw();
void outOfBoundsCheck();
void move();
void addSegment(int x, int y);
void selfCollisionCheck(bool hasEaten);
void setHasMoved(bool a);
void setIsAlive(bool a);
int getX();
int getY();
int getWidth();
int getHeight();
bool getIsAlive();
bool getHasMoved();
std::vector<Segment*> const& getV() const;
private:
std::vector<Segment*> body;
SDL_Texture* headTexture;
SDL_Texture* bodyTexture;
int x;
int y;
int width;
int height;
int dx;
int dy;
int tempX;
int tempY;
bool isAlive;
bool hasMoved;
};
Snake.cpp
Snake::~Snake()
{
}
void Snake::start()
{
// Load Texture
headTexture = loadTexture("gfx/player.png");
bodyTexture = loadTexture("gfx/body.png");
tempX = 0;
tempY = 0;
x = 0;
y = 0;
dx = 0;
dy = 0;
isAlive = true;
hasMoved = false;
width = 0;
height = 0;
SDL_QueryTexture(headTexture, NULL, NULL, &width, &height);
addSegment(x, y);
}
void Snake::update()
{
std::cout << "Head" << body[0]->x << std::endl;
if (body.size() > 1) {
std::cout << "2nd Segment" << body[1]->x << std::endl;
if (body.size() > 2) {
std::cout << "3nd Segment" << body[2]->x << std::endl;
}
}
move();
outOfBoundsCheck();
}
void Snake::draw()
{
if (!isAlive) return; // Cancel the render if player dies
for (int i = 0; i < body.size(); i++) {
blit(headTexture, body[i]->x, body[i]->y);
}
}
void Snake::outOfBoundsCheck()
{
for (int i = 0; i < body.size(); i++) {
if (body[i]->x > SCREEN_WIDTH) {
body[i]->x = 0;
}
if (body[i]->x < 0) {
body[i]->x = SCREEN_WIDTH;
}
if (body[i]->y > SCREEN_HEIGHT) {
body[i]->y = 0;
}
if (body[i]->y < 0) {
body[i]->y = SCREEN_HEIGHT;
}
}
}
void Snake::move()
{
if (app.keyboard[SDL_SCANCODE_W] && dy != 5) {
dx = 0;
dy = -5;
}
if (app.keyboard[SDL_SCANCODE_A] && dx != 5) {
dx = -5;
dy = 0;
}
if (app.keyboard[SDL_SCANCODE_S] && dy != -5) {
dx = 0;
dy = 5;
}
if (app.keyboard[SDL_SCANCODE_D] && dx != -5) {
dx = 5;
dy = 0;
}
Segment* snakeHead = *(body.begin()); //Grid
tempX += dx;
tempY += dy;
if (tempX % 25 == 0) {
snakeHead->x += tempX;
tempX = 0;
}
if (tempY % 25 == 0) {
snakeHead->y += tempY;
tempY = 0;
}
for (int i = body.size() - 1; i > 0; i--) { //For the other parts to follow
body[i]->x = body[i - 1]->x;
body[i]->y = body[i - 1]->y;
}
}
void Snake::addSegment(int x, int y)
{
Segment* seg = new Segment(x, y );
body.push_back(seg);
}
void Snake::selfCollisionCheck(bool hasEaten) // Fail
{
Segment* head = body[0];
if (hasEaten == false) {
for (int i = 1; i < body.size(); i++) {
if (head->x == body[i]->x && head->y == body[i]->y) {
isAlive = false;
break;
}
}
}
else {
return;
}
}
void Snake::setHasMoved(bool a)
{
hasMoved = a;
}
void Snake::setIsAlive(bool a)
{
isAlive = a;
}
int Snake::getX()
{
return x;
}
int Snake::getY()
{
return y;
}
int Snake::getWidth()
{
return width;
}
int Snake::getHeight()
{
return height;
}
bool Snake::getIsAlive()
{
return isAlive;
}
bool Snake::getHasMoved()
{
return hasMoved;
}
std::vector<Segment*> const& Snake::getV() const
{
// TODO: insert return statement here
return body;
}
GameScene.h
#include "Scene.h"
#include "GameObject.h"
#include "Snake.h"
#include "Food.h"
#include "util.h"
#include "text.h"
#include "SoundManager.h"
class GameScene : public Scene
{
public:
GameScene();
~GameScene();
void start();
void draw();
void update();
void spawnFood();
void collisionLogic();
void selfCollision();
void despawnFood(Food* food);
private:
Snake* snake;
Food* food;
int points;
std::vector<Food*> spawnedFood;
};
GameScene.cpp
#include "GameScene.h"
GameScene::GameScene()
{
// Register and add game objects on constructor
snake = new Snake();
this->addGameObject(snake);
points = 0;
}
GameScene::~GameScene()
{
delete snake;
delete food;
}
void GameScene::start()
{
Scene::start();
// Initialize any scene logic here
initFonts();
spawnFood();
}
void GameScene::draw()
{
Scene::draw();
drawText(110, 20, 255, 255, 255, TEXT_CENTER, "POINTS: %03d", points);
if (snake->getIsAlive() == false) {
drawText(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, 255, 255, 255, TEXT_CENTER, "GAME OVER!");
}
}
void GameScene::update()
{
Scene::update();
if (spawnedFood.size() == 0 && spawnedFood.size() != 1) {
spawnFood();
}
collisionLogic();
selfCollision();
}
void GameScene::spawnFood()
{
int random = rand() % 720;
if (random % 25 != 0) {
random = rand() % 720;
}
else {
Food* food = new Food();
this->addGameObject(food);
food->setPosition(rand() % SCREEN_WIDTH, rand() % SCREEN_HEIGHT);
spawnedFood.push_back(food);
}
}
void GameScene::collisionLogic()
{
Segment* head = snake->getV()[0];
std::vector<Segment*> snakeBody = snake->getV();
for (int i = 0; i < objects.size(); i++) {
Food* food = dynamic_cast<Food*>(objects[i]);
if (food != NULL) {
int collision = checkCollision(
head->x, head->y, snake->getWidth(), snake->getHeight(),
food->getX(), food->getY(), food->getWidth(), food->getHeight()
);
if (collision == 1) {
despawnFood(food);
snake->addSegment(snakeBody[snakeBody.size() - 1]->x, snakeBody[snakeBody.size() - 1]->y); //Adds a part to the snake
points++;
break;
}
}
}
}
void GameScene::selfCollision()
{
std::vector<Segment*> body = snake->getV();
Segment* head = snake->getV()[0];
for (int i = 1; i < snake->getV().size(); i++) {
if (head->x == body[i]->x && head->y == body[i]->y) {
snake->setIsAlive(false);
break;
}
}
}
void GameScene::despawnFood(Food* food)
{
int index = -1;
for (int i = 0; i < spawnedFood.size(); i++) {
if (food == spawnedFood[i]) {
index = i;
break;
}
}
if (index != -1) {
spawnedFood.erase(spawnedFood.begin() + index);
delete food;
}
}
It seems that I had some logical errors when it comes to the grid movement because when I re-coded everything and changed the grid movement into cell based instead of using modulo condition by dividing the screen width and height to the pixel size of my snake and using that as the coordinates for my movement, everything went back to normal and the collision bug disappeared.
Instead of doing this for the grid movement
Old Grid Movement Code
tempX += dx;
tempY += dy;
if (tempX % 25 == 0) {
snakeHead->x += tempX;
tempX = 0;
}
if (tempY % 25 == 0) {
snakeHead->y += tempY;
tempY = 0;
}
I defined this as a permanent value in my defs.h
defs.h
#define CELL_SIZE 25 // Size of the segment
#define CELL_WIDTH SCREEN_WIDTH / CELL_SIZE
#define CELL_HEIGHT SCREEN_HEIGHT / CELL_SIZE
After that, since I'm still going to render the picture with the default resolution, I multiplied CELL_SIZE to the dest variable of my blit function
draw.cpp
void blit(SDL_Texture* texture, int x, int y)
{
SDL_Rect dest;
dest.x = x * CELL_SIZE;
dest.y = y * CELL_SIZE;
SDL_QueryTexture(texture, NULL, NULL, &dest.w, &dest.h);
SDL_RenderCopy(app.renderer, texture, NULL, &dest);
}
This results to the snake and any other thing that I'm going to render to follow a grid and by assigning the x and y values with the CELL_WIDTH and CELL_HEIGHT as substitution to the resolution, I accomplished the grid movement with no conflict with my collision check.
I've started programming just recently and I've learned the basic concepts of classes and objects and how to create them. So I decided to try and create a simple game of breakout with what I've learned so far. I've only created the main movable platform with a for cycle and make it move horizontally with the directional keys so far. I've also created a void so the platform doesn't go over the border of the screen but it doesn't work and I've tried all I could think of. Can someone please tell me what I'm doing wrong?
Game::Game( MainWindow& wnd )
:
wnd( wnd ),
gfx( wnd )
{
}
void Game::Go()
{
gfx.BeginFrame();
UpdateModel();
ComposeFrame();
gfx.EndFrame();
}
void Game::UpdateModel()
{
if (wnd.kbd.KeyIsPressed(VK_RIGHT))
{
platform.vx += 3;
}
if (wnd.kbd.KeyIsPressed(VK_LEFT))
{
platform.vx -= 3;
}
platform.ScreenLimit();
}
void Game::ComposeFrame()
{
for (platform.x = 460; platform.x <= platform.w; platform.x++)
{
for (platform.y = 500; platform.y <= platform.h; platform.y++)
{
gfx.PutPixel(platform.x + platform.vx, platform.y, 255, 255, 255);
}
}
}
and here's the header file and source file of the class I created for the platform:
Platform.h
#pragma once
#include "Graphics.h"
class Platform
{
public:
int x = 460;
int y = 500;
int vx = 0;
int width = 60;
int heigth = 10;
int w = x + width;
int h = y + heigth;
void ScreenLimit();
private:
};
Platform.cpp
#include "Platform.h"
void Platform::ScreenLimit()
{
const int left_base = x;
const int right_base = w;
if (right_base >= Graphics::ScreenWidth)
{
x = (Graphics::ScreenWidth - 6) - width;
}
else if (left_base <= 0)
{
x = 0;
}
}
So I was determined to get collision working myself from online resources without asking for help & I successfully followed a tutorial on lazyfoo to get collision working but quickly realised other problems.
So I started trying to get my collision working on my player (just a rect with controls atm) but couldn't actually access the rect inside the player class, I had to initialize it in main & use that for collision which meant transferring my collision function to main (not exactly perfect).
My question: So my collision is limited to two rects which I dedicated to the player & a single asteroid but my idea was to create multiple asteroids coming from the top of the screen, how would I go about altering the below code to accept a vector of "asteroids". Any advice about altering my code to be better object oriented etc is more then welcome but my main problem is collision. Please read collision carefully before posting, the specific X and Y params from the .cpp provides are hardcoded there.
Below Code order:
My current way of defining both player & asteroid for collision
Collision function
Asteroid.cpp & Player.cpp
My new way of loading asteroids - This is what I need collision to work with
Player aPlayer(200, 50, 50, 50);
Asteroid oneAsteroid(200, -50, 50, 50);
bool check_collision(SDL_Rect aPlayer, SDL_Rect oneAsteroid) {
//The sides of the rectangles
int leftA, leftB;
int rightA, rightB;
int topA, topB;
int bottomA, bottomB;
//Calculate the sides of rect A
leftA = aPlayer.X;
rightA = aPlayer.X + aPlayer.width;
topA = aPlayer.Y;
bottomA = aPlayer.Y + aPlayer.height;
//Calculate the sides of rect B
leftB = oneAsteroid.X;
rightB = oneAsteroid.X + oneAsteroid.width;
topB = oneAsteroid.Y;
bottomB = oneAsteroid.Y + oneAsteroid.height;
if (bottomA <= topB)
{
return false;
}
if (topA >= bottomB)
{
return false;
}
if (rightA <= leftB)
{
return false;
}
if (leftA >= rightB)
{
return false;
}
//If none of the sides from A are outside B
return true;
}
#include "asteroids.h"
Asteroid::Asteroid()
{
}
Asteroid::~Asteroid()
{
}
Asteroid::Asteroid(int x, int y, int w, int h)
{
X = x; Y = y; width = w; height = h;
//SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, "Square Constructed with Param(&p)", this);
}
void Asteroid::Render(SDL_Renderer * aRenderer)
{
printf("");
SDL_Rect* aAsteroid = new SDL_Rect();
aAsteroid->x = X; aAsteroid->y = Y; aAsteroid->w = width; aAsteroid->h = height;
SDL_SetRenderDrawColor(aRenderer, 0, 0, 0, 255);
SDL_RenderFillRect(aRenderer, aAsteroid);
}
void Asteroid::Init()
{
velocity.X = 0;
velocity.Y = 5;
}
void Asteroid::Update()
{
Y = Y + velocity.Y;
// printf("%d \n", Astero);
if (Y > 650) {
Y = -50;
}
}
#include "Player.h"
#include "asteroids.h"
using namespace std;
Player::Player()
{
}
Player::~Player()
{
SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, "Player Destroyed (&p)", this);
}
Player::Player(int x, int y, int w, int h)
{
X = x; Y = y; width = w; height = h;
//SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, "Square Constructed with Param(&p)", this);
}
void Player::Init()
{
velocity.X = 10;
velocity.Y = 10;
}
void Player::Update()
{
Y = Y + floorStart;
if (X < 0) {
X = 0;
}
if (KEY_RIGHT == true) {
X++;
}
if (X > SCREEN_WIDTH - 50) {
X = SCREEN_WIDTH - 50;
}
if (Y > SCREEN_HEIGHT - 100) {
Y = SCREEN_HEIGHT - 100;
}
if (KEY_LEFT == true) {
X--;
}
}
void Player::Input(SDL_Event event)
{
if (event.type == SDL_KEYDOWN && event.key.repeat == NULL)
{
if (event.key.keysym.sym == SDLK_LEFT) {
KEY_LEFT = true;
}
else {
KEY_LEFT = false;
}
if (event.key.keysym.sym == SDLK_RIGHT) {
KEY_RIGHT = true;
}
else {
KEY_RIGHT = false;
}
}
if (event.type == SDL_KEYUP && event.key.repeat == NULL) {
if (event.key.keysym.sym == SDLK_LEFT) {
KEY_LEFT = false;
}
if (event.key.keysym.sym == SDLK_RIGHT) {
KEY_RIGHT = false;
}
}
}
void Player::Render(SDL_Renderer * aRenderer)
{
SDL_Rect* thePlayer = new SDL_Rect;
thePlayer->x = X; thePlayer->y = Y; thePlayer->w = width; thePlayer->h = height;
SDL_SetRenderDrawColor(aRenderer, 0, 0, 0, 255);
SDL_RenderFillRect(aRenderer, thePlayer);
//SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, "Rendering (&p)", this);
}
What I need collision to work with, a vector of asteroids:
std::vector<Asteroid*> asteroidList;
asteroidList.push_back(new Asteroid(150, 350, 50, 50));
asteroidList.push_back(new Asteroid(70, 120, 125, 125));
The function to check collision in main.cpp
if (check_collision(aPlayer.thePlayer, oneAsteroid.aAsteroid)) {
printf("#######################");
}
And lastly, how would I go about rendering the array of asteroids?
I am a novice C++ programmer, and I have been experimenting with the SDL libraries for 2d graphics. I have been messing around with try to create some simple GUI controls; however, my button control is having a weird issue that I have been unable to resolve.
Whenever I launch the program in debug mode Visual Studio immediately gives me an error window saying
"Windows has triggered a breakpoint in Default_SDL_Setup.exe.
This may be due to a corruption of the heap, which indicates a bug in
Default_SDL_Setup.exe or any of the DLLs it has loaded.
This may also be due to the user pressing F12 while
Default_SDL_Setup.exe has focus.
The output window may have more diagnostic information."
and pops up a file called crtexe.c in the code editor window.
I have no idea what is wrong or what is going on.
Here is my button header:
#ifndef BUTTON_T
#define BUTTON_T
#include <vector>
#include <string>
#include "SDL.h"
#include "SDL_ttf.h"
#include "SDLFunctions.h"
#endif
class button
{
private:
//refreshes the button
void refresh_image();
bool refresh;
//surface to hold the created text
SDL_Surface *message;
//color of text
SDL_Color tC;
//the different box types
struct boxColor
{
unsigned int r;
unsigned int g;
unsigned int b;
};
boxColor boxes[4];
SDL_Rect rects[4];
//font of text
TTF_Font *f;
/*button's state
* States are:
* 0 - mouseout
* 1 - mouseover
* 2 - mousedown
* 3 - mouseup
*/
int state;
public:
//autosize based off of text?
bool autoSize;
//size of text
int textSize;
//x,y,w,and h for the box
int x, y, w, h;
//text of the label
std::string text;
button(int xpos, int ypos, int width, int height);
~button();
//handles all events for the button
void handleEvents(SDL_Event *event);
//sets text's font style off of a string location, color expects a 3 dimensional array
void setFont(std::string fontFileLocation);
void setFont(int color[3]);
void setFont(std::string fontFileLocation, int color[3]);
//gets the text color as a vector
std::vector<int> textColor();
//returns the color of the specified box
std::vector<int> boxColor(int boxnum);
//sets the color of the specified box, expects a 3 dimensional array
void setBoxColor(int boxnum, int color[3]);
void render(SDL_Surface *screen);
};
Here is the button code:
#include "button.h"
using namespace std;
void button::refresh_image()
{
if (refresh)
{
if (f != NULL)
{
message = TTF_RenderText_Solid(f, text.c_str(), tC);
if ((message != NULL) && autoSize)
{
if (message->w >= w)
{
w = (message->w + 10);
}
if (message->h >= h)
{
h = (message->h + 10);
}
}
}
for (int i = 0; i != 4; ++i)
{
rects[i].x = x;
rects[i].y = y;
rects[i].w = w;
rects[i].h = h;
}
refresh = false;
}
}
button::button(int xpos, int ypos, int width, int height)
{
string defaultFontLocation = DEFAULT_FONT;
//set pos
x = xpos;
y = ypos;
w = width;
h = height;
//set text stuff
text = "";
textSize = DEFAULT_FONT_SIZE;
tC.r = 0;
tC.g = 0;
tC.b = 0;
f = TTF_OpenFont(defaultFontLocation.c_str(), textSize);
message = NULL;
//create box types
state = 0;
for (int i = 0; i != 4; ++i)
{
boxes[i].r = 255;
boxes[i].g = 255;
boxes[i].b = 255;
rects[i].x = x;
rects[i].y = y;
rects[i].w = w;
rects[i].h = h;
}
autoSize = true;
refresh = true;
refresh_image();
}
button::~button()
{
if (f != NULL)
{
TTF_CloseFont(f);
}
if (message != NULL)
{
SDL_FreeSurface(message);
}
}
void button::setFont(string fontFileLocation)
{
if (f != NULL)
{
TTF_CloseFont(f);
}
f = TTF_OpenFont(fontFileLocation.c_str(), textSize);
refresh_image();
}
void button::setFont(int color[3])
{
tC.r = color[0];
tC.g = color[1];
tC.b = color[2];
refresh_image();
}
void button::setFont(string fontFileLocation, int color[3])
{
if (f != NULL)
{
TTF_CloseFont(f);
}
f = TTF_OpenFont(fontFileLocation.c_str(), textSize);
tC.r = color[0];
tC.g = color[1];
tC.b = color[2];
refresh_image();
}
vector<int> button::textColor()
{
vector<int> colors;
colors.resize(3);
colors[0] = tC.r;
colors[1] = tC.g;
colors[2] = tC.b;
return colors;
}
vector<int> button::boxColor(int boxnum)
{
vector<int> colors;
colors.resize(3);
if ((boxnum <= 3) && (boxnum >= 0))
{
colors[0] = boxes[boxnum].r;
colors[1] = boxes[boxnum].g;
colors[2] = boxes[boxnum].b;
} else {
colors[0] = -1;
colors[1] = -1;
colors[2] = -1;
}
return colors;
}
void button::setBoxColor(int boxnum, int color[3])
{
if ((boxnum <= 3) && (boxnum >= 0))
{
boxes[boxnum].r = color[0];
boxes[boxnum].g = color[1];
boxes[boxnum].b = color[2];
//refresh_image();
}
}
void button::render(SDL_Surface *screen)
{
refresh_image();
SDL_FillRect(screen, &rects[state], SDL_MapRGB(screen->format, static_cast<Uint8>(boxes[state].r), static_cast<Uint8>(boxes[state].g), static_cast<Uint8>(boxes[state].b)));
if (message != NULL)
{
apply_surface((((x + w) - message->w) / 2), (((y + h) - message->h) / 2), message, screen);
}
refresh = true;
}
void button::handleEvents(SDL_Event *event)
{
//the mouse offsets
int mx, my;
//if mouse moved
if (event->type == SDL_MOUSEMOTION)
{
//get the mouse offsets
mx = event->motion.x;
my = event->motion.y;
//if the mouse is over the button
if ((mx > x) && (mx < (x + w)) && (my > y) && (my < (y + h)))
{
//set the button sprite
state = 1;
} else {
//set the button sprite
state = 0;
}
}
//if a mouse button was pressed
if (event->type == SDL_MOUSEBUTTONDOWN)
{
//if it was the left mouse button
if (event->button.button == SDL_BUTTON_LEFT)
{
//get the mouse offsets
mx = event->motion.x;
my = event->motion.y;
//if the mouse is over the button
if ((mx > x) && (mx < (x + w)) && (my > y) && (my < (y + h)))
{
//set the button sprite
state = 2;
}
}
}
//if a mouse button was released
if (event->type == SDL_MOUSEBUTTONUP)
{
//if it was the left mouse button
if (event->button.button == SDL_BUTTON_LEFT)
{
//get the mouse offsets
mx = event->motion.x;
my = event->motion.y;
//if the mouse is over the button
if ((mx > x) && (mx < (x + w)) && (my > y) && (my < (y + h)))
{
//set the button sprite
state = 3;
}
}
}
}
and here is the code I have been calling to create the button in my main() function:
int color1[3] = {105,240,81};
int color2[3] = {230,188,62};
button testbutton(360, 130, 50, 30);
testbutton.text = "TEST";
testbutton.setBoxColor(1, color1);
testbutton.setBoxColor(2, color2);
delete[] &color1;
delete[] &color2;
The problem is most probably in these two lines:
delete[] &color1;
delete[] &color2;
color1 and color2are automatic variables, and calling delete on them invokes undefined behavior. You should only delete variables you previously allocated with new.