I do school project on basis of Atari Breakout. I do it in c++ using ALLEGRO 5 library. I don't know how to avoid one problem. When I compile my program i have flickering image on my program and the ball is going too slow. I was trying to change FPS but it still doesn't work properly.
Main loop is collecting informations about position of mouse (paddle), position of ball and bricks left. Than it should print it smoothly on the screen. Do you have any ideas, what i did wrong?
Here is my code:
#include <allegro5/allegro.h>
#include <allegro5\allegro_native_dialog.h>
#include <allegro5/allegro_primitives.h>
#include <allegro5/allegro_font.h>
#include <allegro5/allegro_ttf.h>
#define BRICKS_HORIZONTALLY 10
#define BRICKS_VERTICALLY 5
#define BRICK_WIDTH 102
#define BRICK_HEIGHT 50
#define BRICK_GAP 2
#define PADDLE_WIDTH 100
#define PADDLE_HEIGHT 20
#define PADDLE_POSITION_Y (768-50)
ALLEGRO_DISPLAY *display = NULL;
ALLEGRO_EVENT_QUEUE *event_queue = NULL;
struct ball_typ {
int xv, yv;
int x, y;
};
int playerPaddleEdgeX;
ball_typ ball;
int bricks[BRICKS_VERTICALLY][BRICKS_HORIZONTALLY];
void makeScreenBlack() { //clead screen to black
al_clear_to_color(al_map_rgb(0, 0, 0));
al_flip_display();
}
void resetBricks() {
for (int i = 0; i<BRICKS_VERTICALLY; i++) {
for (int ii = 0; ii<BRICKS_HORIZONTALLY; ii++) {
bricks[i][ii] = 1;
}
}
}
int numberOfBricksRemaining() {
int numberOfBricksRemaining;
numberOfBricksRemaining = 0;
for (int i = 0; i<BRICKS_VERTICALLY; i++) {
for (int ii = 0; ii<BRICKS_HORIZONTALLY; ii++) {
if (bricks[i][ii] != 0) {
numberOfBricksRemaining++;
}
}
}
return numberOfBricksRemaining;
}
void drawingThings() {
makeScreenBlack();
// draw the bricks
for (int i = 0; i<BRICKS_VERTICALLY; i++) {
for (int ii = 0; ii<BRICKS_HORIZONTALLY; ii++) {
if (bricks[i][ii] != 0) {
al_draw_filled_rectangle(ii*BRICK_WIDTH, i*BRICK_HEIGHT,(ii + 1)*BRICK_WIDTH - BRICK_GAP, (i + 1)*BRICK_HEIGHT - BRICK_GAP, al_map_rgb(255, 0, 0));
}
}
}
// draw the ball
al_draw_filled_circle(ball.x, ball.y, 8, al_map_rgb(255, 255, 255));
// draw the player
al_draw_filled_rectangle(playerPaddleEdgeX, PADDLE_POSITION_Y,playerPaddleEdgeX + PADDLE_WIDTH, PADDLE_POSITION_Y + PADDLE_HEIGHT, al_map_rgb(255, 255, 255));
ALLEGRO_FONT *font = al_create_builtin_font();
al_draw_textf(font, al_map_rgb(0, 0, 0), 10, 10, 0, "Player Position (playerPaddleEdgeX is %i)", playerPaddleEdgeX);
al_draw_textf(font, al_map_rgb(0, 0, 0), 10, 20, 0, "ball (x,y) position is (%i, %i)", ball.x, ball.y);
}
void resetBall() {
ball.x = 1024 / 2;
ball.y = 768 / 2;
ball.xv = 4;
ball.yv = 2;
}
int doesOverlap(int objectX, int objectY,
int areaLeft, int areaTop,
int areaRight, int areaBottom) {
if (ball.x > areaLeft &&
ball.x < areaRight &&
ball.y > areaTop &&
ball.y < areaBottom) {
return 1; // 1 here means yes
}
return 0; // 0 here means no
}
void moveBall() {
// update the ball's position for the next frame
ball.x += ball.xv;
ball.y += ball.yv;
// if the ball is overlapping the rectangle
if (ball.yv > 0) { // only if the ball is moving down
if (doesOverlap(ball.x, ball.y,
playerPaddleEdgeX + (PADDLE_WIDTH*0.0),
PADDLE_POSITION_Y,
playerPaddleEdgeX + (PADDLE_WIDTH*0.25),
PADDLE_POSITION_Y + PADDLE_HEIGHT) == 1) {
ball.xv = -5;
ball.yv = -3;
}
if (doesOverlap(ball.x, ball.y,
playerPaddleEdgeX + (PADDLE_WIDTH*0.25),
PADDLE_POSITION_Y,
playerPaddleEdgeX + (PADDLE_WIDTH*0.5),
PADDLE_POSITION_Y + PADDLE_HEIGHT) == 1) {
ball.xv = -3;
ball.yv = -5;
}
if (doesOverlap(ball.x, ball.y,
playerPaddleEdgeX + (PADDLE_WIDTH*0.5),
PADDLE_POSITION_Y,
playerPaddleEdgeX + (PADDLE_WIDTH*0.75),
PADDLE_POSITION_Y + PADDLE_HEIGHT) == 1) {
ball.xv = 3;
ball.yv = -5;
}
if (doesOverlap(ball.x, ball.y,
playerPaddleEdgeX + (PADDLE_WIDTH*0.75),
PADDLE_POSITION_Y,
playerPaddleEdgeX + (PADDLE_WIDTH*1.0),
PADDLE_POSITION_Y + PADDLE_HEIGHT) == 1) {
ball.xv = 5;
ball.yv = -3;
}
}
for (int i = 0; i<BRICKS_VERTICALLY; i++) {
for (int ii = 0; ii<BRICKS_HORIZONTALLY; ii++) {
if (bricks[i][ii] != 0) { // is the brick still here?
if (doesOverlap(ball.x, ball.y,
ii*BRICK_WIDTH, i*BRICK_HEIGHT,
(ii + 1)*BRICK_WIDTH - BRICK_GAP,
(i + 1)*BRICK_HEIGHT - BRICK_GAP) == 1) {
// reverse ball's vertical direction
ball.yv = -ball.yv;
bricks[i][ii] = 0; // erase the brick
}
}
}
}
// bounce off edges of screen
if (ball.x > 1024) {
ball.xv = -ball.xv;
}
if (ball.x < 0) {
ball.xv = -ball.xv;
}
if (ball.y < 0) {
ball.yv = -ball.yv;
}
// but reset ball if it goes off bottom of screen
if (ball.y > 768) {
// lose!
ALLEGRO_MOUSE_STATE state;
al_get_mouse_state(&state);
if (state.buttons & 1) { //reappear ball
resetBall();
}
}
}
void updatePaddlePosition() {
// for now, put the player's paddle where the mouse is
int pos_x = 1024 / 2;
ALLEGRO_MOUSE_STATE state;
al_get_mouse_state(&state);
pos_x = state.x;
playerPaddleEdgeX = pos_x;
}
void gameSetup() {
resetBricks();
resetBall();
// start with the ball off the bottom of the screen
ball.y = 768 + 50;
}
int main() {
ALLEGRO_TIMER * timer = NULL;
int FPS = 60;
al_init(); // allegro initializing
al_init_font_addon();
al_init_primitives_addon();
if (!al_init()){ //check
al_show_native_message_box(NULL, NULL, NULL,
"failed to initialize allegro!", NULL, NULL);
return -1;
}
timer = al_create_timer(1.0 / FPS);
al_install_keyboard();
al_install_mouse();
event_queue = al_create_event_queue();
al_register_event_source(event_queue, al_get_mouse_event_source());
al_register_event_source(event_queue, al_get_timer_event_source(timer));
al_set_new_window_position(20, 30);
display = al_create_display(1024, 768);
if (!display){ //check
al_show_native_message_box(NULL, NULL, NULL,
"failed to initialize display!", NULL, NULL);
return -1;
}
makeScreenBlack();
updatePaddlePosition();
gameSetup();
ALLEGRO_KEYBOARD_STATE key;
al_start_timer(timer);
while (al_key_down(&key, ALLEGRO_KEY_ESCAPE)){
updatePaddlePosition();
moveBall();
if (numberOfBricksRemaining() == 0) {
resetBricks();
}
drawingThings();
al_flip_display();
al_rest(0.01);
}
al_destroy_display(display);
return 0;
}
You're calling al_flip_display twice. You should remove the call to al_flip_display in makeScreenBlack() and keep the other one.
Related
I have to write a function, which detects intersection and returns true or false.
I have Shape.cpp file, and rectangle.cpp, circle.cpp files inherits of it. I tried to calculate it, but i failed. There is no error, but when my program starts, it crashes. MY Question is why it crashes? is my way wrongs? Here is circle.cpp file.
bool Circ::intersects(Shape* pshape)
{
Rect *p1 = dynamic_cast<Rect*>(pshape);
Circ *p2 = dynamic_cast<Circ*>(pshape);
if(p1)
{
float circleDistance_x = abs(p2->getPos().x - p1->getPos().x);
float circleDistance_y = abs(p2->getPos().y - p1->getPos().y);
if(circleDistance_x > (p1->getSize().x/2 + p2->getRad()))
return false;
if(circleDistance_y > (p1->getSize().y/2 + p2->getRad()))
return false;
if(circleDistance_x <= (p1->getSize().x/2))
return true;
if(circleDistance_y <= (p1->getSize().y/2))
return true;
float cornerDistance_sq = (circleDistance_x - (p1->getSize().x/2)) + (circleDistance_y - (p1->getSize().y/2))*(circleDistance_y - (p1->getSize().y/2));
return (cornerDistance_sq <= p2->getRad()^2);
}
return false;
}
This is not the code all i want to write. But when it fails, i stopped to write.
and my Shapes.h file
#ifndef _SHAPES_H
#define _SHAPES_H
struct Point2d
{
float x, y;
};
struct Point3d
{
float r, g, b;
};
class Shape
{
protected:
bool m_bMarked;
Point3d m_col;
Point2d m_veldir;
Point2d m_pos;
float m_vel;
public:
Shape(Point2d& pos, Point2d& veldir, float vel, Point3d& col)
:m_pos(pos),m_veldir(veldir),m_vel(vel),m_col(col)
{
m_bMarked = false;
}
virtual ~Shape() {}
virtual void draw() = 0;
virtual bool intersects(Shape*) = 0;
inline void move() { m_pos.x += m_veldir.x*m_vel; m_pos.y += m_veldir.y*m_vel; }
inline void invert_xdir() { m_veldir.x *= -1; }
inline void invert_ydir() { m_veldir.y *= -1; }
inline void MarkShape() { m_bMarked = true; }
inline void UnMarkShape() { m_bMarked = false; }
inline bool isMarked() { return m_bMarked; }
inline void increase_vel() { m_vel += 0.01f; }
inline void decrease_vel() { m_vel -= 0.01f; }
};
#endif
And finally my ShapesMain.cpp file
#include <time.h>
#include <GL/glut.h>
#include <cmath>
#include "Rectangle.h"
#include "Circle.h"
// YOU CAN CHANGE THE NUMBER OF SHAPES
#define SHAPE_COUNT 20
// YOU CAN MODIFY WINDOW SIZE BY CHANGING THESE
// YOU MAY ALSO VIEW WINDOW IN FULL SCREEN
#define WINDOWX 500
#define WINDOWY 500
// UNCOMMENT THE LINE BELOW TO STOP MOVING SHAPES
//#define NO_MOTION
// CHANGE THESE DIMENSIONS HOWEVER YOU LIKE
#define MAX_SHAPE_DIM 70
#define MIN_SHAPE_DIM 10
float g_windowWidth = WINDOWX;
float g_windowHeight = WINDOWY;
Shape* g_shapeList[SHAPE_COUNT];
int g_numShapes = 0;
bool g_bShowIntersection = true;
//------------------------------------
void Initialize()
{
srand ( time(NULL) );
// delete previous shapes, if there is any
if (g_numShapes > 0)
{
for (int i = 0; i < g_numShapes; i++)
delete g_shapeList[i];
}
// create a new shape repository
do {
g_numShapes = rand() % SHAPE_COUNT; // number of shapes are randomly determined
} while (g_numShapes < 5); // we dont want to have less than 5 shapes
int rect_count = g_numShapes * (rand() % 10 / 10.0f);
int circle_count = g_numShapes - rect_count;
int half_wind_x = 3* g_windowWidth / 4;
int half_wind_y = 3* g_windowHeight / 4;
int max_dim = MAX_SHAPE_DIM; // max dim. of any shape
int min_dim = MIN_SHAPE_DIM; // min dim. of any shape
int quad_wind = g_windowWidth / 4;
for (int i= 0; i<g_numShapes; i++)
{
float x, y;
float v1, v2;
// set positions
do {
x = rand() % half_wind_x;
} while (x <= quad_wind);
do {
y = rand() % half_wind_y;
} while (y <= quad_wind);
Point2d pos = { x,y };
// set velocity directions
do{
v1 = rand() % 10 / 10.0f;
v2 = rand() % 10 / 10.0f;
} while (v1 == 0 || v2 == 0);
v1 *= (rand() % 2) ? -1 : 1;
v2 *= (rand() % 2) ? -1 : 1;
float vnorm = sqrt(v1*v1 + v2*v2);
Point2d veldir = { v1 / vnorm, v2 / vnorm };
// set velocity
float vel;
do {
vel = rand() % 2 / 10.0f;
} while (vel == 0);
#ifdef NO_MOTION
vel = 0.0f;
#endif
//set color
float R = rand()%100/100.0f;
float G = rand()%100/100.0f;
float B = rand()%100/100.0f;
Point3d color = { R,G,B };
// construct objects
if (i < rect_count)
{
float wx;
float wy;
do {
wx = rand() % quad_wind;
} while (wx < min_dim || wx>max_dim);
do {
wy = rand() % quad_wind;
} while (wy < min_dim || wy>max_dim);
Point2d size = { wx, wy };
Rect* pRect = new Rect(pos, size, veldir, vel, color);
g_shapeList[i] = pRect;
}
else
{
float rad;
do {
rad = rand() % quad_wind;
} while (rad < min_dim || rad>max_dim);
Circ* pCirc = new Circ(pos, rad, veldir, vel, color);
g_shapeList[i] = pCirc;
}
}
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
}
//-------------------------------------
// This function handles the intersections of shapes.
// if the user is not interested in marking intersections
// s/he can set bMarkIntersections to false..in this case
// no intersection test is performed
void MarkObjects(bool bMarkIntersections)
{
if (bMarkIntersections == false)
{
for (int i = 0; i < g_numShapes; i++)
g_shapeList[i]->UnMarkShape();
}
else
{
// reset the states of all shapes as unmarked
for (int i = 0; i < g_numShapes; i++)
g_shapeList[i]->UnMarkShape();
for (int i = 0; i < g_numShapes; i++)
{
for (int j = i+1; j < g_numShapes; j++)
{
if (g_shapeList[i]->intersects(g_shapeList[j]))
{
g_shapeList[i]->MarkShape();
g_shapeList[j]->MarkShape();
}
}
}
}
}
//------------------------------------
void UpdateData()
{
// create viewport bounding rectangles to keep the shapes within the viewport
Point2d Winpos = { -1.0,0.0 };
Point2d Winsize = { 1.0 , g_windowHeight };
Point2d Winveldir = { 0,0 }; // dummy veldir
float Winvel = 0.0f; //not moving
Point3d Wincol = { 0,0,0 }; // dummy color
Rect WindowRectLeft(Winpos, Winsize, Winveldir, Winvel, Wincol);
Winpos.x = 0.0; Winpos.y = -1.0;
Winsize.x = g_windowWidth; Winsize.y = 1.0;
Rect WindowRectBottom(Winpos, Winsize, Winveldir, Winvel, Wincol);
Winpos.x = g_windowWidth; Winpos.y = 0.0;
Winsize.x = 1; Winsize.y = g_windowHeight;
Rect WindowRectRight(Winpos, Winsize, Winveldir, Winvel, Wincol);
Winpos.x = 0.0; Winpos.y = g_windowHeight;
Winsize.x = g_windowWidth; Winsize.y = 1.0f;
Rect WindowRectUp(Winpos, Winsize, Winveldir, Winvel, Wincol);
for (int i = 0; i < g_numShapes; i++)
{
// move the shape
g_shapeList[i]->move();
// if it bounces to the window walls, invert its veldir
if (g_shapeList[i]->intersects(&WindowRectLeft) ||
g_shapeList[i]->intersects(&WindowRectRight))
g_shapeList[i]->invert_xdir();
if (g_shapeList[i]->intersects(&WindowRectBottom) ||
g_shapeList[i]->intersects(&WindowRectUp))
g_shapeList[i]->invert_ydir();
}
}
//------------------------------------
void ChangeSize(GLsizei w, GLsizei h)
{
if(h == 0)
h = 1;
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
g_windowHeight = h;
g_windowWidth = w;
glOrtho(0, g_windowWidth, 0, g_windowHeight , 1.0f, -1.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
//------------------------------------
void processNormalKeys(unsigned char key, int x, int y)
{
if (key == 'q') // PRESS 'q' to terminate the application
exit(0);
if(key=='r') // PRESS 'r' ket to reset the shapes
Initialize();
if (key == 's') // toggle between showing the intersections or not
g_bShowIntersection = g_bShowIntersection ? false: true;
}
//------------------------------------
void processSpecialKeys(int key, int x, int y)
{
switch(key) {
case GLUT_KEY_LEFT :
break;
case GLUT_KEY_RIGHT :
break;
case GLUT_KEY_UP:
// PRESSING UP ARROW KEY INCREASES THE SHAPE VELOCITIES
for (int i = 0; i < g_numShapes; i++)
g_shapeList[i]->increase_vel();
break;
case GLUT_KEY_DOWN:
// PRESSING DOWN ARROW KEY DECREASES THE SHAPE VELOCITIES
for (int i = 0; i < g_numShapes; i++)
g_shapeList[i]->decrease_vel();
break;
}
}
//-------------------------------------
void display() {
glClear(GL_COLOR_BUFFER_BIT); // Clear the color buffer
glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
UpdateData();
MarkObjects(g_bShowIntersection);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
for (int i= 0; i<g_numShapes; i++)
g_shapeList[i]->draw();
glutSwapBuffers();
}
//------------------------------------
int main(int argc, char* argv[])
{
glutInit(&argc, argv); // Initialize GLUT
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB );
glutInitWindowPosition(100,100);
glutInitWindowSize(WINDOWX, WINDOWY);
glutCreateWindow("COM102B - PA4");
// Register callback handler for window re-paint
glutDisplayFunc(display);
glutReshapeFunc(ChangeSize);
glutIdleFunc(display);
glutKeyboardFunc(processNormalKeys);
glutSpecialFunc(processSpecialKeys);
Initialize();
glutMainLoop(); // Enter infinitely event-processing loop
return 0;
}
Your problem is in these lines:
Rect *p1 = dynamic_cast<Rect*>(pshape);
Circ *p2 = dynamic_cast<Circ*>(pshape);
Unless you had inherited Rect from Circ or vice versa this is what makes your program crash, you can't cast your pShape to Circ if it is a Rect, so when you pass a Rect object to your function it will correctly cast to Rect* but it will fail with Circ* returning nullptr, so then when you try to access methods from p2 it will crash becouse you are accessing to invalid memory (0x00000000) :
if(p1)
{
float circleDistance_x = abs(p2->getPos().x - p1->getPos().x);
float circleDistance_y = abs(p2->getPos().y - p1->getPos().y);
if(circleDistance_x > (p1->getSize().x/2 + p2->getRad()))
return false;
if(circleDistance_y > (p1->getSize().y/2 + p2->getRad()))
return false;
if(circleDistance_x <= (p1->getSize().x/2))
return true;
if(circleDistance_y <= (p1->getSize().y/2))
return true;
float cornerDistance_sq = (circleDistance_x - (p1->getSize().x/2)) + (circleDistance_y - (p1->getSize().y/2))*(circleDistance_y - (p1->getSize().y/2));
return (cornerDistance_sq <= p2->getRad()^2);
}
So, you could simply just cast the first p1 pointer since the method is from circle, it's obvious that it was called from a Circ Object so there's no need for p2 pointer.
Rect *p1 = dynamic_cast<Rect*>(pshape);
if(p1)
{
float circleDistance_x = abs(getPos().x - p1->getPos().x);
float circleDistance_y = abs(getPos().y - p1->getPos().y);
if(circleDistance_x > (p1->getSize().x/2 + getRad()))
return false;
if(circleDistance_y > (p1->getSize().y/2 + getRad()))
return false;
if(circleDistance_x <= (p1->getSize().x/2))
return true;
if(circleDistance_y <= (p1->getSize().y/2))
return true;
float cornerDistance_sq = (circleDistance_x - (p1->getSize().x/2)) + (circleDistance_y - (p1->getSize().y/2))*(circleDistance_y - (p1->getSize().y/2));
return (cornerDistance_sq <= getRad()^2);
}
Also on the line:
return (cornerDistance_sq <= getRad()^2)
i think you are trying to get the radius square but this wont do it, what it is actually doing is
(cornerDistance_sq <= getRad()) ^ 2
becouse <= has greater precedence to ^, plus ^ is not a square operator it is a bitwise operator. So what you actually want is :
return cornerDistance_sq <= getRad() * getRad();
As the title suggests, I am trying to implement collision with scrolling.
The code here isn't the tidiest and it doesn't make use of object-oriented programming. But this code is a prototype for collision in a game I am making so I can reuse in that game.
Anyway, when I wrote this code and implemented no scrolling, the collision worked fine. However, when I implemented scrolling, suddenly, one pixel of the rectangle that represent the player gets stuck in the rectangles I've used to test the collision.
Here's the code.
Main.cpp:
#include "SDL.h"
#include "SDL_image.h"
#include "SDL_mixer.h"
#include "SDL_ttf.h"
using namespace std;
int main(int argc, char *argv[]) {
SDL_Init(SDL_INIT_EVERYTHING);
IMG_Init(IMG_INIT_PNG | IMG_INIT_JPG);
Mix_Init(MIX_INIT_MP3);
Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, 2, 640);
TTF_Init();
SDL_Window *Window = SDL_CreateWindow("Test", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1000, 600, SDL_WINDOW_SHOWN);
SDL_Renderer *Renderer = SDL_CreateRenderer(Window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
bool quit = false;
SDL_Event Event;
SDL_Rect Box;
Box.w = 25;
Box.h = 25;
Box.x = 500 - int(Box.w / 2);
Box.y = 300 - int(Box.h / 2);
int CAMERA_X = 0;
int CAMERA_Y = 0;
int xVel = 0;
int yVel = 0;
SDL_Rect RECTS[3];
RECTS[0].x = 50;
RECTS[0].y = 50;
RECTS[0].w = 50;
RECTS[0].h = 100;
RECTS[1].x = 150;
RECTS[1].y = 50;
RECTS[1].w = 50;
RECTS[1].h = 100;
RECTS[2].x = 250;
RECTS[2].y = 50;
RECTS[2].w = 50;
RECTS[2].h = 100;
SDL_Rect CAM_RECTS[3];
CAM_RECTS[0].x = 50;
CAM_RECTS[0].y = 50;
CAM_RECTS[0].w = 50;
CAM_RECTS[0].h = 100;
CAM_RECTS[1].x = 150;
CAM_RECTS[1].y = 50;
CAM_RECTS[1].w = 50;
CAM_RECTS[1].h = 100;
CAM_RECTS[2].x = 250;
CAM_RECTS[2].y = 50;
CAM_RECTS[2].w = 50;
CAM_RECTS[2].h = 100;
const Uint8 *Input = NULL;
while (!quit) {
Input = SDL_GetKeyboardState(NULL);
while (SDL_PollEvent(&Event)) {
if (Event.type == SDL_QUIT) {
quit = true;
}
}
if (Input[SDL_SCANCODE_RIGHT]) {
xVel = -7;
} else if (Input[SDL_SCANCODE_LEFT]) {
xVel = 7;
} else {
xVel = 0;
}
if (Input[SDL_SCANCODE_UP]) {
yVel = 7;
} else if (Input[SDL_SCANCODE_DOWN]) {
yVel = -7;
} else {
yVel = 0;
}
for (unsigned int i = 0; i < 3; i++) {
CAM_RECTS[i].x = RECTS[i].x + CAMERA_X;
CAM_RECTS[i].y = RECTS[i].y + CAMERA_Y;
}
CAMERA_X += xVel;
for (unsigned int i = 0; i < 3; i++) {
if (Box.x <= CAM_RECTS[i].x + CAM_RECTS[i].w && Box.x + Box.w >= CAM_RECTS[i].x && Box.y <= CAM_RECTS[i].y + CAM_RECTS[i].h && Box.y + Box.h >= CAM_RECTS[i].y) {
if (Box.x <= CAM_RECTS[i].x + CAM_RECTS[i].w && Box.x + Box.w >= CAM_RECTS[i].x) {
CAMERA_X += -xVel;
}
}
}
CAMERA_Y += yVel;
for (unsigned int i = 0; i < 3; i++) {
if (Box.x <= CAM_RECTS[i].x + CAM_RECTS[i].w && Box.x + Box.w >= CAM_RECTS[i].x && Box.y <= CAM_RECTS[i].y + CAM_RECTS[i].h && Box.y + Box.h >= CAM_RECTS[i].y) {
if (Box.y <= CAM_RECTS[i].y + CAM_RECTS[i].h && Box.y + Box.h >= CAM_RECTS[i].y) {
CAMERA_Y += -yVel;
}
}
}
SDL_SetRenderDrawColor(Renderer, 0, 0, 0, 255);
SDL_RenderClear(Renderer);
SDL_SetRenderDrawColor(Renderer, 255, 255, 255, 255);
SDL_RenderFillRect(Renderer, &Box);
SDL_SetRenderDrawColor(Renderer, 255, 255, 255, 255);
for (unsigned int i = 0; i < 3; i++) {
SDL_RenderFillRect(Renderer, &CAM_RECTS[i]);
}
SDL_RenderPresent(Renderer);
}
Input = NULL;
SDL_DestroyRenderer(Renderer);
SDL_DestroyWindow(Window);
TTF_Quit();
Mix_CloseAudio();
Mix_Quit();
IMG_Quit();
SDL_Quit();
return 0;
}
Please help.
Thank you very much :)
Ok, I changed answer, now it should work without jittering.
It's definitely not the best solution, but it would depends on wider concepion of your program.
int sign(int x)
{
return (x > 0) - (x < 0);
}
/* Movement values are updated by referenced arguments.*/
void check_collisions(SDL_Rect* obj_rects, unsigned num_of_obj,
SDL_Rect obstacle, int& horizontal_move, int& vertical_move)
{
for (unsigned int i = 0; i < num_of_obj; i++)
{
int obj_new_x = obj_rects[i].x + horizontal_move;
// Horizontal collision
if (obj_new_x < (obstacle.x + obstacle.w)
&& (obj_new_x + obj_rects[i].w) > obstacle.x
&& obj_rects[i].y < (obstacle.y + obstacle.h)
&& (obj_rects[i].h + obj_rects[i].y) > obstacle.y)
{
// Calculate maximal possible horizontal movement.
if (sign(horizontal_move) == 1)
horizontal_move = obstacle.x - (obj_rects[i].x + obj_rects[i].w);
else if (sign(horizontal_move) == -1)
horizontal_move = (obstacle.x + obstacle.w) - obj_rects[i].x;
}
int obj_new_y = obj_rects[i].y + vertical_move;
// Vertical collision
if (obj_rects[i].x < (obstacle.x + obstacle.w)
&& (obj_rects[i].x + obj_rects[i].w) > obstacle.x
&& obj_new_y < (obstacle.y + obstacle.h)
&& (obj_new_y + obj_rects[i].h) > obstacle.y)
{
if (sign(vertical_move) == 1)
vertical_move = obstacle.y - (obj_rects[i].y + obj_rects[i].h);
else if (sign(vertical_move) == -1)
vertical_move = (obstacle.y + obstacle.h) - obj_rects[i].y;
}
}
}
int cam_velocity = 5;
...
while (!quit) {
...
if (Input[SDL_SCANCODE_RIGHT])
{
x_movement = cam_velocity;
}
else if (Input[SDL_SCANCODE_LEFT])
{
x_movement = -cam_velocity;
}
if (Input[SDL_SCANCODE_UP])
{
y_movement = -cam_velocity;
}
else if (Input[SDL_SCANCODE_DOWN])
{
y_movement = cam_velocity;
}
check_collisions(CAM_RECTS, 3, Box, x_movement, y_movement);
CAMERA_X += x_movement;
CAMERA_Y += y_movement;
for (unsigned int i = 0; i < 3; i++) {
CAM_RECTS[i].x = RECTS[i].x + CAMERA_X;
CAM_RECTS[i].y = RECTS[i].y + CAMERA_Y;
}
...
Okay so I am a college student and our professor gave us this code to examine, and I was wondering if there was another way to do this but for OS X. My professor is using a HANDLE which I barely understand what that is, the professor was telling me he create the HANDLE as a pointer to the output stream so what would be the equivalent to it for mac since we don't have #include Windows.h obviously. Everything you see in this code is my professor's, including the comments.
//This is an example of a simple platformer made in the console. This
//makes no claims as the best way of doing things as I created this
//live before a class (while taking suggestions from them).
#include <iostream>
#include <string>
#include <vector>
#include <Windows.h>
using namespace std;
const int MAX_ROWS = 20;
const int MAX_COLS = 60;
//this is a reference to cout (we got this when we changed the output color)
//we can use this to setCursorPosition
HANDLE output = GetStdHandle(STD_OUTPUT_HANDLE);
//this is the place that we can set the cursor to when we are not using it
COORD zero;
//basic cardinal directions
enum Direction
{
UP = 8,
DOWN = 2,
RIGHT = 6,
LEFT = 4,
NORTH = UP,
SOUTH = DOWN,
EAST = RIGHT,
WEST = LEFT
};
//each place on the gameboard is a tile (tiles in this game are 1 character in length, though they do not have to be)
class Tile
{
public:
char display;
bool isPassible;
COORD pos;
Tile(char d, bool b, int y, int x)
{
display = d;
isPassible = b;
pos.X = x;
pos.Y = y;
}
void Display()
{
SetConsoleCursorPosition(output, pos);
cout << display;
SetConsoleCursorPosition(output, zero);
}
};
class Player
{
public:
COORD pos;
char display;
int JumpAmt;
//player constructor (x and y are starting location)
Player(int x, int y)
{
pos.X = x;
pos.Y = y;
display = 'C';
JumpAmt = 0;
}
//This gets the input and decides how to use it (this should be called in the main game loop)
bool Act(vector<vector<Tile>> GameBoard)
{
bool didMove = false;
COORD oldPos;
oldPos.X = pos.X;
oldPos.Y = pos.Y;
if (GetAsyncKeyState(VK_RIGHT) & 0x8000)
{
//make sure the movement is not off the game board and that there is not a wall in the way
if (pos.X + 1 < MAX_COLS && GameBoard[pos.Y][pos.X + 1].isPassible)
{
//actually move the character
pos.X += 1;
didMove = true;
}
}
if (GetAsyncKeyState(VK_LEFT) & 0x8000)
{
if (pos.X - 1 > 0 && GameBoard[pos.Y][pos.X - 1].isPassible)
{
pos.X -= 1;
didMove = true;
}
}
//You can only jump if you are on the ground
if (pos.Y + 1 < MAX_ROWS && !(GameBoard[pos.Y + 1][pos.X].isPassible))
{
if (GetAsyncKeyState(VK_UP) & 0x8000)
{
if (pos.Y - 1 > 0 && GameBoard[pos.Y - 1][pos.X].isPassible)
{
pos.Y -= 1;
didMove = true;
JumpAmt = 4;
}
}
}
//When you are not jumping fall (gravity)
if (JumpAmt == 0)
{
if (pos.Y + 1 < MAX_ROWS && GameBoard[pos.Y + 1][pos.X].isPassible)
{
pos.Y += 1;
didMove = true;
}
}
//This is what happens during your jump
if (JumpAmt > 0)
{
JumpAmt--;
if (pos.Y - 1 > 0 && GameBoard[pos.Y - 1][pos.X].isPassible)
{
pos.Y -= 1;
didMove = true;
}
}
//If you did move anywhere then update the board
if (didMove)
{
Display(oldPos, GameBoard);
}
return didMove;
}
void Display()
{
//draw myself at my position
SetConsoleCursorPosition(output, pos);
cout << display;
SetConsoleCursorPosition(output, zero);
}
void Display(COORD fix, vector<vector<Tile>> GameBoard)
{
//clear my old position
GameBoard[fix.Y][fix.X].Display();
Display();
}
};
int main()
{
//zero is used after anything is drawn to reset the cursor (this should never be changed after this)
zero.X = 0;
zero.Y = 0;
//this is a 2 dimentional array of tiles
vector<vector<Tile>> GameBoard;
//init all the tiles to blank (we will later add in platforms and stuff over top of these)
for (int row = 0; row < MAX_ROWS; row++)
{
vector<Tile> thisRow;
for (int col = 0; col < MAX_COLS; col++)
{
thisRow.push_back(Tile(' ', true, row, col));
}
GameBoard.push_back(thisRow);
}
//Build the game specific tiles (in a perfect world these would be read in from a file)
GameBoard[4][2] = Tile('-', false,4,2);
GameBoard[4][3] = Tile('-', false, 4,3);
GameBoard[4][4] = Tile('-', false, 4,4);
GameBoard[4][5] = Tile('-', false, 4,5);
GameBoard[4][6] = Tile('-', false, 4,6);
GameBoard[7][9] = Tile('-', false, 7,9);
GameBoard[7][10] = Tile('-', false, 7,10);
GameBoard[5][10] = Tile('-', false, 5,10);
GameBoard[8][14] = Tile('*', false, 8, 14); //this marks the win square
//display the board once
for (int row = 0; row < MAX_ROWS; row++)
{
for (int col = 0; col < MAX_COLS; col++)
{
GameBoard[row][col].Display();
}
}
//Bob is our hero
Player bob = Player(3, 3);
while (true)
{
bob.Act(GameBoard);
bob.Display();
Sleep(50);
//if bob falls down he dies
if (bob.pos.Y > 18)
{
bob.pos.X = 3;
bob.pos.Y = 3;
//bob.display = 65 + rand() % 26;
}
//if bob gets here he wins
if (bob.pos.Y == 7 && bob.pos.X == 14)
{
COORD pos;
pos.Y = 20;
pos.X = 0;
SetConsoleCursorPosition(output, pos);
cout << "You are Awesome";
break;
}
}
COORD pos;
pos.Y = 21;
pos.X = 0;
SetConsoleCursorPosition(output, pos);
system("Pause");
return 0;
}
I have multiple SDL_Rects creating a snake that is supposed to stay in a specific area. Sometimes when the "snake" reaches the boundaries a part disappears.
void Snake::update(SDL_Surface *screen, int level)
{
old_pos.first = snake_rect[0];
if(x_axis)
snake_rect[0].x += snake_speed * level * direction_multiplier;
else if(!x_axis)
snake_rect[0].y += snake_speed * level * direction_multiplier;
for(unsigned int i = 1; i < snake_rect.size(); ++i)
{
old_pos.second = snake_rect[i];
snake_rect[i] = old_pos.first;
old_pos.first = old_pos.second;
}
boundariesCheck(screen);
/// Making the enemy move randomly
if(rand() % 100 < 10)
{
if(x_axis)
{
x_axis = false;
direction.second = rand() % 2;
if(direction.second)
direction_multiplier = 1;
else if(!direction.second)
direction_multiplier = -1;
}
else if(!x_axis)
{
x_axis = true;
direction.first = rand() % 2;
if(direction.first)
direction_multiplier = 1;
else if(!direction.first)
direction_multiplier = -1;
}
}
}
void Snake::draw(SDL_Surface *screen)
{
for(unsigned int i = 1; i < snake_rect.size(); ++i)
{
SDL_FillRect(screen, &snake_rect[i], 0xFF0000);
}
SDL_FillRect(screen, &snake_rect[0], 0xFF5500);
}
I am creating a version of Conway's Game of Life. It is eventually going to be run on an Arduino and will control LEDs so the memory footprint is important. It seems that I have a memory leak, I believe that this leak occurs whilst frreing a two dimensional array. If anyone could help me with this then I would be very grateful.
Thanks,
Joe
VLD's output is:
c:\projects\gameoflifecpp\gameoflifecpp\gameoflifecpp.cpp (72): GameOfLifeCPP.exe!GenerateGrid + 0xA bytes
c:\projects\gameoflifecpp\gameoflifecpp\gameoflifecpp.cpp (185): GameOfLifeCPP.exe!ProcessGrid + 0x7 bytes
c:\projects\gameoflifecpp\gameoflifecpp\gameoflifecpp.cpp (46): GameOfLifeCPP.exe!wmain + 0x9 bytes
f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c (552): GameOfLifeCPP.exe!__tmainCRTStartup + 0x19 bytes
f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c (371): GameOfLifeCPP.exe!wmainCRTStartup
0x7C817077 (File and line number not available): kernel32.dll!RegisterWaitForInputIdle + 0x49 bytes
Code is:
// GameOfLifeCPP.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#include <vld.h>
#define WIDTH 75
#define HEIGHT 88
#define GENERATION_COUNT_LIMIT -1
long _generationCount = 0;
// These get set by controls on the table
long _delay = 1000;
bool _run = true;
bool _trail = true;
bool _randomize = false;
char* _colours = "roy";
int _tmain(int argc, _TCHAR* argv[])
{
system("pause");
short** grid = GenerateGrid(false);
short** trailGrid = GenerateGrid(true); // This is used to record all prev cells
while(_run)
{
if (_randomize)
{
grid = GenerateGrid(false);
trailGrid = GenerateGrid(true);
// Fade out LEDs
// Clear the historical grids that we compare
_randomize = false;
_generationCount = 0;
}
OutputGrid(grid, trailGrid);
if (_trail)
trailGrid = CalculateTrailGrid(grid, trailGrid);
short** nextGrid = ProcessGrid(grid);
// Release the old grid
for(int i = 0; i < sizeof(nextGrid); i++)
{
delete(grid[i]);
}
delete(grid);
grid = nextGrid;
// We don't want to just sleep we need to find out the start and end time
Sleep(_delay);
bool foundRecurance = false;
// Need to detect recurence, have a buffer of 5-10 prev grids and one
// hundredth ago, one thousanth etc that we compare to.
_generationCount++;
if (foundRecurance || _generationCount == GENERATION_COUNT_LIMIT)
_randomize = true;
_CrtDumpMemoryLeaks();
//system("pause");
}
return 0;
}
short** GenerateGrid(bool empty)
{
// The coordinates are y,x because it is simpler to output a row of chars
// when testing in the command line than it is to output a column of chars
short** grid = new short*[HEIGHT];
for(int y = 0; y < HEIGHT; y++)
{
short* row = new short[WIDTH];
for(int x = 0; x < WIDTH; x++)
{
// There is no point creating random numbers that we aren't going
// to use
if (empty)
row[x] = 0;
else
row[x] = rand() % 5 == 1 ? 1 : 0;
// Might want to adjust this or make it random
}
grid[y] = row;
}
return grid;
}
void OutputGrid(short** grid, short** trailGrid)
{
// This is terribly inefficent but I don't care since it is only for
// testing on my laptop
system("cls");
HANDLE hConsole;
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
for(int y = 0; y < HEIGHT; y++)
{
for(int x = 0; x < WIDTH; x++)
{
int curState = grid[y][x];
if (curState == 0 && _trail) // If it isn't alive then show the trail
curState = trailGrid[y][x];
switch (curState)
{
case 0: SetConsoleTextAttribute(hConsole, 0); break;
case 1: SetConsoleTextAttribute(hConsole, GetColour(0)); break;
case 2: SetConsoleTextAttribute(hConsole, GetColour(1)); break;
case -1: SetConsoleTextAttribute(hConsole, GetColour(2)); break;
}
//if (curState == 1 || curState == 2)
// std::cout << "*";
//else
std::cout << " ";
}
SetConsoleTextAttribute(hConsole, 15);
std::cout << std::endl;
}
}
int GetColour(int index)
{
int colour = 0;
switch(_colours[index])
{
case 'r': colour = 12; break;
case 'o': colour = 6; break;
case 'y': colour = 14; break;
}
colour = colour * 16;
return colour;
}
int ProcessCell(short** grid, int x, int y)
{
// Get the value for each of the surrounding cells
// We use the formula (x - 1 + WIDTH) % WIDTH because that means that if the
// Current cell is at 0,0 then top left is WIDTH-1,WIDTH-1 and so on.
// This makes the grid wrap around.
// We don't care if the cells value is 1 or 2 it is either live or dead
int topLeft = (
grid[(y - 1 + HEIGHT) % HEIGHT][(x - 1 + WIDTH) % WIDTH] > 0) ? 1 : 0;
int top = (grid[(y - 1 + HEIGHT) % HEIGHT][x] > 0) ? 1 : 0;
int topRight =
(grid[(y - 1 + HEIGHT) % HEIGHT][(x + 1 + WIDTH) % WIDTH] > 0) ? 1 : 0;
int left = (grid[y][(x - 1 + WIDTH) % WIDTH] > 0) ? 1 : 0;
int self = (grid[y][x] > 0) ? 1 : 0;
int right = (grid[y][(x + 1 + WIDTH) % WIDTH] > 0) ? 1 : 0;
int bottomLeft =
(grid[(y + 1 + HEIGHT) % HEIGHT][(x - 1 + WIDTH) % WIDTH] > 0) ? 1 : 0;
int bottom = (grid[(y + 1 + HEIGHT) % HEIGHT][x] > 0) ? 1 : 0;
int bottomRight =
(grid[(y + 1 + HEIGHT) % HEIGHT][(x + 1 + WIDTH) % WIDTH] > 0) ? 1 : 0;
// Count up the surrounding cells to decide the current cell's state
int liveCount = topLeft + top + topRight + left +
right + bottomLeft + bottom + bottomRight;
int live = 0;
if (self > 0)
{
// Both are alive, just different colours
if (liveCount == 2)
live = 1;
if (liveCount == 3)
live = 2;
}
else if (liveCount == 3)
{
// Brought back to life, we don't care that it is the wrong
// colour - it looks better
live = 1;
}
return live;
}
short** ProcessGrid(short** grid)
{
short** nextGrid = GenerateGrid(true);
for (int y = 0; y < HEIGHT; y++)
{
for (int x = 0; x < WIDTH; x++)
{
nextGrid[y][x] = ProcessCell(grid, x, y);
}
}
return nextGrid;
}
short** CalculateTrailGrid(short** grid, short** trailGrid)
{
// Any previously live cells are marked
short** nextGrid = GenerateGrid(true);
for (int y = 0; y < HEIGHT; y++)
{
for (int x = 0; x < WIDTH; x++)
{
int state = grid[y][x];
if (state == 0)
state = trailGrid[y][x]; // Not alive currently but was
if (state != 0)
state = -1;
nextGrid[y][x] = state;
}
}
return nextGrid;
}
Just a quick 5 min cleanup in notepad... should give you some ideas... avoids any possible memory leaks...
#include "stdafx.h"
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#include <vld.h>
#include <vector>
#define WIDTH 75
#define HEIGHT 88
#define GENERATION_COUNT_LIMIT -1
long _generationCount = 0;
// These get set by controls on the table
long _delay = 1000;
bool _run = true;
bool _trail = true;
bool _randomize = false;
char* _colours = "roy";
typedef std::vector<std::vector<short>> grid_t; // Use std::vector
int _tmain(int argc, _TCHAR* argv[])
{
system("pause");
grid_t grid = GenerateGrid(false);
grid_t trailGrid = GenerateGrid(true); // This is used to record all prev cells
while(_run)
{
if (_randomize)
{
grid = GenerateGrid(false);
trailGrid = GenerateGrid(true);
// Fade out LEDs
// Clear the historical grids that we compare
_randomize = false;
_generationCount = 0;
}
OutputGrid(grid, trailGrid);
if (_trail)
trailGrid = CalculateTrailGrid(grid, trailGrid);
grid_t nextGrid = ProcessGrid(grid);
// Release the old grid
grid = nextGrid;
// We don't want to just sleep we need to find out the start and end time
Sleep(_delay);
bool foundRecurance = false;
// Need to detect recurence, have a buffer of 5-10 prev grids and one
// hundredth ago, one thousanth etc that we compare to.
_generationCount++;
if (foundRecurance || _generationCount == GENERATION_COUNT_LIMIT)
_randomize = true;
_CrtDumpMemoryLeaks();
//system("pause");
}
return 0;
}
grid_t GenerateGrid(bool empty)
{
// The coordinates are y,x because it is simpler to output a row of chars
// when testing in the command line than it is to output a column of chars
grid_t grid;
for(int y = 0; y < HEIGHT; y++)
{
std::vector<short> row;
for(int x = 0; x < WIDTH; x++)
row[x] = empty ? 0 : rand() % 5 == 1 ? 1 : 0;
grid.push_back(row);
}
return grid;
}
void OutputGrid(const grid_t& grid, const grid_t& trailGrid)
{
// This is terribly inefficent but I don't care since it is only for
// testing on my laptop
system("cls");
HANDLE hConsole;
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
for(int y = 0; y < HEIGHT; y++)
{
for(int x = 0; x < WIDTH; x++)
{
int curState = grid[y][x];
if (curState == 0 && _trail) // If it isn't alive then show the trail
curState = trailGrid[y][x];
switch (curState)
{
case 0: SetConsoleTextAttribute(hConsole, 0); break;
case 1: SetConsoleTextAttribute(hConsole, GetColour(0)); break;
case 2: SetConsoleTextAttribute(hConsole, GetColour(1)); break;
case -1: SetConsoleTextAttribute(hConsole, GetColour(2)); break;
}
}
SetConsoleTextAttribute(hConsole, 15);
std::cout << std::endl;
}
}
int GetColour(int index)
{
switch(_colours[index])
{
case 'r': return 16 * 12;
case 'o': return 16 * 6;
case 'y': return 16 * 14;
default: return 0;
}
}
int ProcessCell(const grid_t& grid, int x, int y)
{
// Get the value for each of the surrounding cells
// We use the formula (x - 1 + WIDTH) % WIDTH because that means that if the
// Current cell is at 0,0 then top left is WIDTH-1,WIDTH-1 and so on.
// This makes the grid wrap around.
// We don't care if the cells value is 1 or 2 it is either live or dead
int topLeft = (grid[(y - 1 + HEIGHT) % HEIGHT][(x - 1 + WIDTH) % WIDTH] > 0) ? 1 : 0;
int top = (grid[(y - 1 + HEIGHT) % HEIGHT][x] > 0) ? 1 : 0;
int topRight = (grid[(y - 1 + HEIGHT) % HEIGHT][(x + 1 + WIDTH) % WIDTH] > 0) ? 1 : 0;
int left = (grid[y][(x - 1 + WIDTH) % WIDTH] > 0) ? 1 : 0;
int self = (grid[y][x] > 0) ? 1 : 0;
int right = (grid[y][(x + 1 + WIDTH) % WIDTH] > 0) ? 1 : 0;
int bottomLeft = (grid[(y + 1 + HEIGHT) % HEIGHT][(x - 1 + WIDTH) % WIDTH] > 0) ? 1 : 0;
int bottom = (grid[(y + 1 + HEIGHT) % HEIGHT][x] > 0) ? 1 : 0;
int bottomRight = (grid[(y + 1 + HEIGHT) % HEIGHT][(x + 1 + WIDTH) % WIDTH] > 0) ? 1 : 0;
// Count up the surrounding cells to decide the current cell's state
int liveCount = topLeft + top + topRight + left + right + bottomLeft + bottom + bottomRight;
int live = 0;
if (self > 0)
{
// Both are alive, just different colours
if (liveCount == 2)
live = 1;
if (liveCount == 3)
live = 2;
}
else if (liveCount == 3)
{
// Brought back to life, we don't care that it is the wrong
// colour - it looks better
live = 1;
}
return live;
}
grid_t ProcessGrid(const grid_t& grid)
{
grid_t nextGrid = GenerateGrid(true);
for (int y = 0; y < HEIGHT; y++)
{
for (int x = 0; x < WIDTH; x++)
nextGrid[y][x] = ProcessCell(grid, x, y);
}
return nextGrid;
}
grid_t CalculateTrailGrid(const grid_t& grid, const grid_t& trailGrid)
{
// Any previously live cells are marked
grid_t nextGrid = GenerateGrid(true);
for (int y = 0; y < HEIGHT; y++)
{
for (int x = 0; x < WIDTH; x++)
nextGrid[y][x] = state == 0 ? trailGrid[y][x] : -1;
}
return nextGrid;
}