I am currently trying to make a cellular automata. I am just getting the basics of direction, movement and rendering.
However, when running the compiler the cells don't move despite calling the Move function.
Here are the files,
Cell.cpp
#include "Cell.h"
#include "CellManager.h"
Cell::Cell()
{
Lifetime = 5 + rand() % 2 - 1;
}
Cell::~Cell()
{
}
void Cell::Move(int dir)
{
switch (dir)
{
default: y -= 2;
break;
case 0: y -= 2;
break;
case 1: x += 2;
break;
case 2: y += 2;
break;
case 3: x -= 2;
break;
}
if (x > 800)
{
x = 0;
} else if (x < 0)
{
x = 800;
}
if (y > 800)
{
y = 0;
}
else if (y < 0)
{
y = 800;
}
}
int Cell::ChangeDir(int dir)
{
dir = rand() % 3;
return dir;
}
void Cell::Draw(sf::RenderTarget& target)
{
sf::RectangleShape cell;
cell.setSize(sf::Vector2f(2.f,2.f));
cell.setOutlineColor(colour);
cell.setPosition(x, y);
target.draw(cell);
}
void Cell::SetUp(int X, int Y, sf::Color Colour, int dir)
{
x = X;
y = Y;
colour = Colour;
Dir = dir;
}
CellManager.cpp
#include "CellManager.h"
#include "Cell.h"
void CellManager::UpdateCells(vector<Cell> cells, sf::RenderTarget& target)
{
for (int i = 0; i < cells.size(); i++)
{
cells[i].ChangeDir(cells[i].Dir);
cells[i].Move(cells[i].Dir);
cells[i].Draw(target);
}
}
void CellManager::CreateInstance()//TODO
{
}
I do not understand where I am going wrong as the switch statement works but the cells just refuse to move. Any help would be appreciated :)
Your function, CellManager::UpdateCell's parameter vector<Cell> cells COPIES the vector of cells, then changes the copies. You probably want to pass by reference instead. This would look like: std::vector<Cell>& cells.
Other note:
ChangeDir does not change the member variable Dir. You could pass in by reference for that as well, or just not pass in anything at all and use Dir = rand() % 3;.
Related
This program is supposed to have a map made out of dots and a player which you can move around.
But when I opened this program one day, the text was flickering and moving up and down.
It uses Windows.h to redraw on the console without flickering and to hide the cursor
Does it have to do something with the cmd properties, the code or the Windows.h header file?
#include <iostream>
#include <conio.h>
#include <Windows.h>
char map[1000][1000];
int width = 100;
int height = 10;
char Tmt = '.';
void cls()
{
COORD cursorPosition;
cursorPosition.X = 0;
cursorPosition.Y = 0;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), cursorPosition);
}
void hidcur()
{
HANDLE consoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO info;
info.dwSize = 100;
info.bVisible = FALSE;
SetConsoleCursorInfo(consoleHandle, &info);
}
class Player {
public:
int x;
int y;
char sym;
void Draw()
{
map[x][y] = sym;
}
void Logic()
{
if (x < 1) { x++; }
if (y < 1) { y++; }
if (x > width) { x--; }
if (y > height) { y--; }
}
void Input()
{
if (_kbhit())
{
switch (_getch())
{
case 'w':
map[x][y] = Tmt;
y--;
break;
case 'a':
map[x][y] = Tmt;
x--;
break;
case 's':
map[x][y] = Tmt;
y++;
break;
case 'd':
map[x][y] = Tmt;
x++;
break;
case 'p':
system("cls");
break;
}
}
}
void PrintPos()
{
printf("Pos:\n");
if (x >= 10) { printf(" %d\n", x); }
else { printf(" 0%d\n", x); }
if (y >= 10) { printf(" %d\n", y); }
else { printf(" 0%d\n", y); }
}
};
Player player1;
void Setup()
{
player1.x = 2;
player1.y = 2;
player1.sym = '#';
player1.Draw();
player1.Logic();
for (int mapsui = 1; mapsui <= width; mapsui++)
{
for (int mapsuj = 1; mapsuj <= height; mapsuj++)
{
map[mapsui][mapsuj] = Tmt;
}
}
}
void DrawMap()
{
player1.PrintPos();
printf("\n\n\n");
for (int drawi = 1; drawi <= width; drawi++)
{
for (int drawj = 1; drawj <= height; drawj++)
{
printf("%c", map[drawj][drawi]);
}
printf("\n");
}
}
int main()
{
Setup();
while (1)
{
DrawMap();
player1.Input();
player1.Logic();
player1.Draw();
cls();
hidcur();
}
return 0;
}
In the DrawMap method, when you have the two for loops, you are checking width in the outer loop and height in the inner loop, while it should be the other way round. Note that the outer loop controls the number of lines, and as you are limiting it to the width (100) you are displaying 100 lines most of which are empty, because Setup just initializes 10 lines. As the command window shows less lines (I think it's about 30 by default or something like that) the map goes up and that results in the flicker you see. It should be:
for (int drawi = 1; drawi <= height; drawi++)
{
for (int drawj = 1; drawj <= width; drawj++)
{
printf("%c", map[drawj][drawi]);
}
printf("\n");
}
Note than in Setup you also use the loops in this way (the outer loop checks width and the inner loop checks height) but in that case you are later using the indexes to the map the other way round (first i and then j) so that results in the correct initialization of the map (10 rows of 100 columns).
Somewhere in the following code I am missing something. My rects are being drawn outside of the console window and they all need to be within the console. This code is a hack job for a class of mine so I apologize for unnecessary or incorrect code. Sometimes it works but most times it just draws things outside the window. How can I contain the code?
#include "stdafx.h"
#define NOMINMAX
#include <stdio.h>
#include <windows.h>
#include <conio.h>
#include <time.h>
void moveCursor(int x, int y)
{
COORD c = { x,y };
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), c);
}
struct Vec2
{
short x, y;
int min, max;
Vec2() : x(rand()% 50), y(rand()%20 ){ }
Vec2(int x, int y) : x(x), y(y) { }
void operator+=(Vec2 v)
{
x += v.x;
y += v.y;
}
};
class Rect
{
Vec2 min, max;
public:
void setMin(Vec2 const & min)
{
this->min = min;
}
void setMax(Vec2 const & max)
{
this->max = max;
}
void setRandom(Rect & r)
{
int x = rand() % 50;
int y = rand() % 20;
int x2 = rand() % 8+3;
int y2 = rand() % 8+3;
Vec2 min(x , y);
r.setMin(min);
Vec2 max(x + x2, y + y2);
r.setMax(max);
}
Rect(int minx, int miny, int maxx, int maxy)
:min(minx, miny), max(maxx, maxy)
{}
Rect() {}
void draw(const char letter) const
{
for (int row = min.y; row < max.y; row++)
{
for (int col = min.x; col < max.x; col++)
{
if (row >= 0 && col >= 0)
{
moveCursor(col, row);
putchar(letter);
}
}
}
}
bool isOverlapping(Rect const & r) const
{
return !(min.x >= r.max.x || max.x <= r.min.x
|| min.y >= r.max.y || max.y <= r.min.y);
}
void translate(Vec2 const & delta)
{
min += (delta);
max += (delta);
}
};
int main()
{
// initialization
srand(time (NULL));
const int Number_of_rects = 5;
Rect *userRect = new Rect(7, 5, 10, 9);
Rect rect[5]{};
int userInput;
do
{
// draw
for (int i = 0; i < Number_of_rects; i++)
{
rect[i].draw('0'+i);
};
moveCursor(0, 0); // re-print instructions
printf("move with 'w', 'a', 's', and 'd'");
userRect->draw('#');
// user input
userInput = _getch();
// update
Vec2 move;
switch (userInput)
{
case 'w': move = Vec2(0, -1); break;
case 'a': move = Vec2(-1, 0); break;
case 's': move = Vec2(0, +1); break;
case 'd': move = Vec2(+1, 0); break;
}
userRect->draw(' '); // un-draw before moving
userRect->translate(move);
} while (userInput != 27); // escape key
delete userRect;
return 0;
}
The '#' are always there, 1 and 0 were drawn but are colliding(different problem) and 2,3,and 4 are being drawn off screen
I'm currently trying to write a menu function for one of my projects. I'm remaking pac-man and I'd like to be able to modularize the main menu, calling it when I want it to appear. I'm thinking an SDL_surface and a TTF font are all I need as parameters for this particular function.
I ran into trouble when I used SDL functions only available in SDL 1.2 as opposed to 2.0. I would like this code to be as reusable as possible. How would you guys approach this problem? I have some sample code below, though not all of it is my own. I'd like to get something like this working:
int showmenu(SDL_Surface* screen, TTF_Font* font)
{
Uint32 time;
int x, y;
const int NUMMENU = 2;
const char* labels[NUMMENU] = {"Continue","Exit"};
SDL_Surface* menus[NUMMENU];
bool selected[NUMMENU] = {0,0};
SDL_Color color[2] = {{255,255,255},{255,0,0}};
menus[0] = TTF_RenderText_Solid(font,labels[0],color[0]);
menus[1] = TTF_RenderText_Solid(font,labels[1],color[0]);
SDL_Rect pos[NUMMENU];
pos[0].x = screen->clip_rect.w/2 - menus[0]->clip_rect.w/2;
pos[0].y = screen->clip_rect.h/2 - menus[0]->clip_rect.h;
pos[1].x = screen->clip_rect.w/2 - menus[0]->clip_rect.w/2;
pos[1].y = screen->clip_rect.h/2 + menus[0]->clip_rect.h;
SDL_FillRect(screen,&screen>clip_rect,SDL_MapRGB(screen>format,0x00,0x00,0x00));
SDL_Event event;
while(1)
{
time = SDL_GetTicks();
while(SDL_PollEvent(&event))
{
switch(event.type)
{
case SDL_QUIT:
SDL_FreeSurface(menus[0]);
SDL_FreeSurface(menus[1]);
return 1;
case SDL_MOUSEMOTION:
x = event.motion.x;
y = event.motion.y;
for(int i = 0; i < NUMMENU; i += 1)
{
if(x >= pos[i].x && x <= pos[i].x + pos[i].w &&
y >= pos[i].y && y <= pos[i].y + pos[i].h)
{
if(!selected[i])
{
selected[i] = 1;
SDL_FreeSurface(menus[i]);
menus[i] = TTF_RenderText_Solid(font,labels[i],color[1]);
}
}
else
{
if(selected[i])
{
selected[i] = 0;
SDL_FreeSurface(menus[i]);
menus[i] = TTF_RenderText_Solid(font,labels[i],color[0]);
}
}
}
break;
case SDL_MOUSEBUTTONDOWN:
x = event.button.x;
y = event.button.y;
for(int i = 0; i < NUMMENU; i += 1)
{
if(x >= pos[i].x && x <= pos[i].x + pos[i].w &&
y >= pos[i].y && y <= pos[i].y + pos[i].h)
{
SDL_FreeSurface(menus[0]);
SDL_FreeSurface(menus[1]);
return i;
}
}
break;
case SDL_KEYDOWN:
if(event.key.keysym.sym == SDLK_ESCAPE)
{
SDL_FreeSurface(menus[0]);
SDL_FreeSurface(menus[1]);
return 0;
}
}
}
for(int i = 0; i < NUMMENU; i += 1)
{
SDL_BlitSurface(menus[i],NULL,screen,&pos[i]);
}
}
}
beginner to C++ and attempting a dungeon crawler beginner task, upon testing one of the classes I found that printing the 2D array works, however if it is edited and printed, it resets and prints original values it was initialised with.
InitGrid is used to initialize the array.
class MAP
{
public:
/*
Difficulty used in number of enemies and traps created.
1-5 Difficulty
| 1 - Too easy | 2 - Easy | 3 - Normal | 4 - Hard | 5 - Insane |
*/
int Difficulty = Hard; //### Temporary, user selection needs implemented ###
int SpawnPos;
int TPosX; //Treasure Postion, used to checkwinstate.
int TPosY; //Treasure Postion, used to checkwinstate.
char Grid[MAPHeight][MAPWidth];
void InitGrid()
{
for (int y = 0; y < 9; y++) //Row loop
{
for (int x = 0; x < 14; x++) //Column loop
{
Grid[y][x] = { '.' };
}
}
}
void PrintMap()
{
for (int y = 0; y < 9; y++) //This loops on the rows.
{
for (int PrintX = 0; PrintX < 14; PrintX++) //This loops on the columns
{
cout << Grid[y][PrintX] << " ";
}
cout << endl;
}
}
void GenerateEnemies()
{
for (int i = 0; i < Difficulty; i++)
{
int TotEnemies = (Difficulty * 1.5);
for (TotEnemies; TotEnemies == 0; TotEnemies--)
{
int x = rand() % (MAPWidth - 1);
int y = rand() % (MAPHeight - 1);
if (Grid[y][x] == '.')
{
Grid[y][x] = '#';
}
else
{
GenerateEnemies();
}
}
}
}
// Generate Enemies
void GenerateTraps()
{
for (int i = 0; i < Difficulty; i++)
{
int TotTraps = (Difficulty * 1.5);
for (TotTraps; TotTraps == 0; TotTraps--)
{
int x = rand() % (MAPWidth - 1);
int y = rand() % (MAPHeight - 1);
if (Grid[y][x] == '.')
{
Grid[y][x] = 'T';
}
else
{
GenerateTraps();
}
}
}
}
void GenerateTreasure()
{
int x = rand() % MAPWidth;
int y = rand() % MAPHeight;
/*
Randomly selects spawn location
uses tmp variables to overwrite
that grid location.
*/
if (Grid[y][x] == '.')
{
Grid[y][x] = 'X';
}
else
{
GenerateTreasure();
}
TPosX = x;
TPosY = y;
}
};
//PLAYER CLASS
class PLAYER : public MAP
{
public:
int Health = (Difficulty * 1.5);
int PPosX;
int PPosY;
char Direction; //Use cin to get user input after map is updated, used in switch case to move player.
void GenerateSpawn()
{
int x = rand() % (MAPWidth - 1);
int y = rand() % (MAPHeight - 1);
/*
Randomly selects spawn location
uses tmp variables to overwrite
that grid location.
*/
Grid[y][x] = 'P';
PPosX = x;
PPosY = y;
}
void AllowMove(int y, int x)
{
if (Grid[y][x] == '.')
{
Grid[y][x] = '#';
}
else if (Grid[y][x] == 'X')
{
//GameWin();
}
else if (Grid[y][x] == '#')
{
//DamagePlayer();
}
else {}
}
void MovePlayer()
{
switch (Direction)
{
case 'w':
{
int x = PPosX;
int y = (PPosY + 1);
void AllowMove(int y, int x);
}
break;
case 'a':
{
int x = (PPosX - 1);
int y = PPosY;
void AllowMove(int y, int x);
}
break;
case 's':
{
int x = (PPosX);
int y = PPosY;
void AllowMove(int y, int x);
}
break;
case 'd':
{
int x = (PPosX + 1);
int y = PPosY;
void AllowMove(int y, int x);
}
break;
default:
cout << "invalid character, try again." << endl;
Sleep(5000);
//Call function to retry
}
}
};
//######### End #########
//Main Function
int main() {
srand(time(NULL)); //Used to seed rand() values.
SetConsoleTitle(TEXT("Dungeon Crawler"));
//Objects
MAP Map;
PLAYER Player;
Map.InitGrid();
Player.GenerateSpawn();
//Map.GenerateTreasure();
//Map.GenerateEnemies();
//Map.GenerateTraps();
Map.PrintMap();
cout << endl;
}
However, when I run these, I get the following image:
I've attempted debugging in visual studio using breakpoints and at some point it does set the grid value to 'P' but I couldn't find where I gets 'reset' for lack of a better term.
char Grid[MAPHeight][MAPWidth]; needs to be moved outside of the class as a global variable. Currently as the PLAYER class inherits from the MAPS class, when GenerateSpawn() edits the Grid that is created specific to the object linked to PLAYER.
When it is a global variable, it is separate, then when edited by GenerateSpawn() and called by void PrintMap() they both use the same Grid.
That way when it is printed to console it correctly prints out the map.
Answered my own question in case someone else stumbles upon this.
I am new to c++ and I have been practicing collision in a small game program that does nothing and I just can't get the collision right
So I use images loaded into variables
background = oslLoadImageFile("background.png", OSL_IN_RAM, OSL_PF_5551);
sprite = oslLoadImageFile("sprite.png", OSL_IN_RAM, OSL_PF_5551);
bush = oslLoadImageFile("bush.png", OSL_IN_RAM, OSL_PF_5551);
While there are variables stored like
sprite->x = 3;
if ( (sprite->x + spritewidth > bush->x) && (sprite->x < bush->x + bushwidth) && (sprite->y + spriteheight > bush->y) && (sprite->y < bush->y + bushheight) )
{
bushcol = 1;
}
else
{
bushcol = 0;
}
So when i press a button
if (osl_keys->held.down)
{
if (bushcol == 1)
{
sprite->y = bush->y + 38;
}
else
{
sprite->y += 3;
}
}
if (osl_keys->held.up)
{
if (bushcol == 1)
{
sprite->y = bush->y - 23;
}
else
{
sprite->y -= 3;
}
}
if (osl_keys->held.right)
{
if (bushcol == 1)
{
sprite->x = bush->x - 28;
}
else
{
sprite->x += 3;
}
}
if (osl_keys->held.left)
{
if (bushcol == 1)
{
sprite->x = bush->x + 28;
}
else
{
sprite->x -= 3;
}
}
i was thinking of things like
sprite->y = bushheight - 24;
but it doesnt work
Any suggestions?
I'd suggest making a function solely for the purpose of bounding box colision detection.
It could look like
IsColiding(oslImage item1, oslImage item2)
{
/* Perform check */
}
in which you perform the check if there is a collision between image 1 and image 2.
As for the algorithm you're trying to use check out this wikipedia for example AABB bounding box
Especially this part:
In the case of an AABB, this tests
becomes a simple set of overlap tests
in terms of the unit axes. For an AABB
defined by M,N against one defined by
O,P they do not intersect if (Mx>Px)
or (Ox>Nx) or (My>Py) or (Oy>Ny) or
(Mz>Pz) or (Oz>Nz).
I think you have the basic idea. Just check your work. Here is a simple version which compiles:
#import <stdlib.h>
typedef struct {
// I'm going to say x, y, is in the center
int x;
int y;
int width;
int height;
} Rect;
Rect newRect(int x, int y, int w, int h) {
Rect r = {x, y, w, h};
return r;
}
int rectsCollide(Rect *r1, Rect *r2) {
if (r1->x + r1->width/2 < r2->x - r2->width/2) return 0;
if (r1->x - r1->width/2 > r2->x + r2->width/2) return 0;
if (r1->y + r1->height/2 < r2->y - r2->height/2) return 0;
if (r1->y - r1->height/2 > r2->y + r2->height/2) return 0;
return 1;
}
int main() {
Rect r1 = newRect(100,200,40,40);
Rect r2 = newRect(110,210,40,40);
Rect r3 = newRect(150,250,40,40);
if (rectsCollide(&r1, &r2))
printf("r1 collides with r2\n");
else
printf("r1 doesnt collide with r2\n");
if (rectsCollide(&r1, &r3))
printf("r1 collides with r3\n");
else
printf("r1 doesnt collide with r3\n");
}
First of all i suppose you mean
sprite->y = bush->**y** - 3;
second i dont know what platform you are using, but often times the y-coordinates are inverted. i.e., y=0 corresponds to top of the screen. In that case your comparisons might not work.
third collision checking can quickly become complicated when you add rotation and non-rectangular objects to it. You should consider using CGAL or some other computational geometry algorithms library, which can handle polygon intersection.