I am trying to build simple game (with help from online tutorial) that imitate conway's game of life. I put grid on screen.
When user tap into grid, it will disable/enable the dots, and when user clicked play button, dots on grid will evolve based on conway's game of life rules.
however there is a problem, after all code done, and I tried to run a simulation ( I enable some dots on grid).
and clicked play button, nothing happened, I clicked play button twice, and Xcode logged out this message:
GameOfLife2[823:43706] -[CCNode schedule:interval:repeat:delay:] : Selector 'step1' was already scheduled on <MainScene = 0x7fca01e69590 | Name = >
for details about few of my methods related to this error (posted on Mainscene.m)
#import "MainScene.h"
#import "Grid.h"
#implementation MainScene {
Grid *_grid;
CCTimer *_timer;
CCLabelTTF *_generationLabel;
CCLabelTTF *_populationLabel;
}
- (id)init
{
self = [super init];
if (self) {
_timer = [[CCTimer alloc] init];
}
return self;
}
- (void)play
{
[self schedule:#selector(step1) interval:0.05f];}
- (void)pause
{
[self unschedule:#selector(step1)];
}
- (void)step1
{
[_grid evolveStep];
_generationLabel.string = [NSString stringWithFormat:#"%d", _grid.generation];
_populationLabel.string = [NSString stringWithFormat:#"%d", _grid.totalAlive];
}
#end
on Grid.m
-(void)evolveStep{
[self countNeighbors];
[self updateCreatures];
_generation++;
}
-(void)countNeighbors
{
for (int i = 0; i < [_gridArray count]; i++)
{
for (int j = 0; j < [_gridArray[i] count]; j++)
{
Creature *currentCreature = _gridArray[i][j];
currentCreature.livingNeighbors = 0;
for (int x = (i-1) ; x <= (i+1); x++)
{
for (int y = (j-1); y <= (j+1); y++)
{
BOOL isIndexValid;
isIndexValid = [self isIndexValidForX:x andY:y];
if (!((x == i) && (y == j)) && isIndexValid)
{
Creature *neighbor = _gridArray[x][y];
if (neighbor.isAlive)
{
currentCreature.livingNeighbors +=1;
}
}
}
}
}
}
}
-(void)updateCreatures{
_totalAlive = 0;
for (int l = 0; l <= [_gridArray count]; l++) {
for (int k = 0; [_gridArray[l] count]; k++) {
Creature *currentCreature = _gridArray[l][k];
if (currentCreature.livingNeighbors == 3) {
currentCreature.isAlive = YES;
} else if ( (currentCreature.livingNeighbors <= 1) || (currentCreature.livingNeighbors >= 4) ) {
currentCreature.isAlive = NO;
}
if (currentCreature.isAlive) {
_totalAlive++;
}
}
}
}
tried to google out this problem, still no solutions yet.
Related
I'm trying implement a doodle jump video game. So far my program works well except the fact that platform are being generated rapidly rather than slowly being incremented as the player proceeds upwards. I'm using the cinder framework to implement it and using the poScene cinderblock to help me with the game flow and animation. The doodle character and each platform is a single jpg.
From my understanding, I think the platform is being generated every time update() is being called, which occurs at every frame. I tried using "std::chrono_duration_cast" to get time in ticks to cause a delay in the update function being called, but it doesn't seem to work.
I also tried calling the manipulatePlatform in Setup() but if I do that, the image of platform is not being generated.
using namespace cinder;
using cinder::app::KeyEvent;
namespace myapp {
using namespace po::scene;
using cinder::app::KeyEvent;
using po::scene::ImageView;
using po::scene::View;
MyApp::MyApp() {
state_ = GameState::kPlaying;
speed_ = 20;
}
void MyApp::setup() {
SoundSetUp(background_sound_,"BackgroundMusic.wav");
mViewController = ViewController::create();
my_scene = Scene::create(mViewController);
//setUpIntro();
}
void MyApp::DrawBackground() {
cinder::gl::Texture2dRef texture2D = cinder::gl::Texture::create(
cinder::loadImage(MyApp::loadAsset("background.jpg")));
cinder::gl::draw(texture2D, getWindowBounds());
}
void MyApp::SetUpCharacter() {
my_scene->getRootViewController()->getView()->addSubview(character);
}
void MyApp::SetUpPlatform() {
my_scene->getRootViewController()->getView()->addSubview(platform);
}
void MyApp::ManipulatePlatform() {
cinder::gl::Texture2dRef texture_platform = cinder::gl::Texture::create(
cinder::loadImage(MyApp::loadAsset("platform.jpg")));
platform = po::scene::ImageView::create(texture_platform);
my_scene->getRootViewController()->getView()->addSubview(platform);
point array[20];
for (int i = 0; i < 10; i++) {
array[i].x = cinder::Rand::randInt() % 400;
array[i].y = cinder::Rand::randInt() % 533;
}
if (y < h) {
for (int i = 0; i < 10; i++) {
y = h;
array[i].y = array[i].y - change_in_height;
if (array[i].y > 533) {
array[i].y = 0;
array[i].x = cinder::Rand::randInt() % 400;
}
}
}
auto end = std::chrono::steady_clock::now();
for (int i = 0; i < 10; i++) {
platform->setPosition(array[i].x, array[i].y);
}
}
void MyApp::SimulateGame() {
cinder::gl::Texture2dRef texture_character = cinder::gl::Texture::create(
cinder::loadImage(MyApp::loadAsset("doodle.jpg")));
character = po::scene::ImageView::create(texture_character);
my_scene->getRootViewController()->getView()->addSubview(character);
point array[20];
change_in_height = change_in_height + 0.2;
y = y + change_in_height;
if (y > 500) {
change_in_height = change_in_height - 10;
}
for (int i = 0; i < 10; i++) {
if ((x + 50 > array[i].x) && (x + 20 < array[i].x + 68)
&& (y + 70 > array[i].y) && (y + 70 < array[i].y + 14) && (change_in_height > 0)) {
change_in_height = -10;
}
}
character->setPosition(x, y);
}
void MyApp::update() {
auto start = std::chrono::steady_clock::now();
ManipulatePlatform();
SimulateGame();
auto end = std::chrono::steady_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::seconds>(end - start).count();
while (duration < 100) {
std::cout << duration++;
}
my_scene->update();
}
void MyApp::draw() {
my_scene->getRootViewController()->getView()->removeAllSubviews();
DrawBackground();
SetUpPlatform();
SetUpCharacter();
my_scene->draw();
}
void MyApp::keyDown(KeyEvent event) {
switch (event.getCode()) {
case KeyEvent::KEY_RIGHT:
x = x + 50;
break;
case KeyEvent::KEY_LEFT:
x = x - 50;
}
}
void MyApp::ResetGame() {
my_scene->getRootViewController()->getView()->removeAllSubviews();
}
void MyApp::SoundSetUp(cinder::audio::VoiceRef &audio_object, std::string file_path) {
cinder::audio::SourceFileRef sourceFile = cinder::audio::load(MyApp::loadAsset(file_path));
audio_object = cinder::audio::Voice::create(sourceFile);
audio_object->start();
}
void MyApp::setUpIntro() {
intro_background_doodle_jump = cinder::gl::Texture::create(
cinder::loadImage(MyApp::loadAsset("intro.jpg")));
intro_background_doodle_jump->setCleanBounds(cinder::Area(0, 0 , getWindowWidth(), getWindowHeight()));
}
}// namespace myapp
so recently I have been wanting to make a snake game in C++ using SFML in Microsoft Visual studio 2015 and I made one and I am actually pretty satisfied with my work but there is a problem, that I forgot to make a game over for it and it seems like I couldn't make it work and it really had me on edge. So I thought I could use stack overflow's help. I would really appreciate it if you guys would let me know how to make it work and please keep it simple obvious.
Here is my code:
// GraphicalLoopSnakeGame.cpp : Defines the entry point for the console application.
#include "stdafx.h"
#include <ctime>
#include <SFML/Graphics.hpp>
using namespace sf;
int N = 30, M = 20;
int size = 16;
int w = size * N;
int h = size * M;
int dir, num = 4;
struct Snake {
int x, y;
} s[100];
struct Fruit {
int x, y;
} f;
void Tick() {
for(int i = num; i > 0; --i) {
s[i].x = s[i - 1].x;
s[i].y = s[i - 1].y;
}
if(dir == 0) s[0].y += 1;
if(dir == 1) s[0].x -= 1;
if(dir == 2) s[0].x += 1;
if(dir == 3) s[0].y -= 1;
if((s[0].x == f.x) && (s[0].y == f.y)) {
num++;
f.x = rand() % N;
f.y = rand() % M;
}
if(s[0].x > N) s[0].x = 0;
if(s[0].x < 0) s[0].x = N;
if(s[0].y > M) s[0].y = 0;
if(s[0].y < 0) s[0].y = M;
for(int i = 1; i < num; i++)
if(s[0].x == s[i].x && s[0].y == s[i].y) num = i;
}
int main() {
srand(time(0));
RenderWindow window(VideoMode(w, h), "Snake Game!");
Texture t1, t2, t3;
t1.loadFromFile("images/white.png");
t2.loadFromFile("images/red.png");
t3.loadFromFile("images/green.png");
Sprite sprite1(t1);
Sprite sprite2(t2);
Sprite sprite3(t3);
Clock clock;
float timer = 0, delay = 0.13;
f.x = 10;
f.y = 10;
while(window.isOpen()) {
float time = clock.getElapsedTime().asSeconds();
clock.restart();
timer += time;
Event e;
while(window.pollEvent(e)) {
if(e.type == Event::Closed) window.close();
}
if(Keyboard::isKeyPressed(Keyboard::Left)) dir = 1;
if(Keyboard::isKeyPressed(Keyboard::Right)) dir = 2;
if(Keyboard::isKeyPressed(Keyboard::Up)) dir = 3;
if(Keyboard::isKeyPressed(Keyboard::Down)) dir = 0;
if(Keyboard::isKeyPressed(Keyboard::W)) dir = 3;
if(Keyboard::isKeyPressed(Keyboard::D)) dir = 2;
if(Keyboard::isKeyPressed(Keyboard::A)) dir = 1;
if(Keyboard::isKeyPressed(Keyboard::S)) dir = 0;
if(timer > delay) {
timer = 0;
Tick();
}
////// draw ///////
window.clear();
for(int i = 0; i < N; i++)
for(int j = 0; j < M; j++) {
sprite1.setPosition(i * size, j * size);
window.draw(sprite1);
}
for(int i = 0; i < num; i++) {
sprite2.setPosition(s[i].x * size, s[i].y * size);
window.draw(sprite2);
}
sprite3.setPosition(f.x * size, f.y * size);
window.draw(sprite3);
window.display();
}
return 0;
}
In your Tick() function you can check whether the head bumps into anything after everything has moved in the given direction. If it does, let main() know about it somehow: for example, return a bool which expresses if the game is over. Let's say this bool is called over.
So, add if (over) { window.close(); } inside your while (window.isOpen()) loop (right after calling Tick()) to let main() reach return 0; and finish the program.
EDIT: Think about using std::deque for moving your snake using less code and time: you'd be able to just pop_back() the snake tile farthest from the head and push_front() the new tile where the head currently is (after a tick), simulating crawling one step forwards.
Anyway, after having moved your snake you can check each of its body tiles whether it has the same coordinates as its head. If it does, it means your snake crashed into its tail so the game is over.
// in Tick():
// ...other logic...
tiles.pop_back();
tiles.push_front(new_head_position);
for (/* each tile of your snake except its head */) {
if (tile.x == head.x && tile.y == head.y) {
return false; // game over
}
}
return true; // everything is fine
The picture not showing and when I close, error appear. I can’t figure it out, maybe a problem with pointers.
stackoverflow is asking for details, but I have no more details - sorry.
stackoverflow is asking for details, but I have no more details - sorry.
stackoverflow is asking for details, but I have no more details - sorry.
stackoverflow is asking for details, but I have no more details - sorry.
stackoverflow is asking for details, but I have no more details - sorry.
Menu.h
#include "Picture.h"
class menu
{
const int menuPictCount;
picture* menuPicture[];
public:
menu(sf::RenderWindow& usableArea);
~menu();
void draw();
void posСorrection();
void shineButton(sf::Color color);
};
Menu.cpp <--------- the problem is here
menu::menu(sf::RenderWindow& usableArea) : menuPictCount(4)
{
this->menuPicture[this->menuPictCount];
//background
this->menuPicture[0] = new picture(usableArea, "image/background/0.png");
//buttons
this->menuPicture[1] = new picture(usableArea, "image/menu/newgame.png");
this->menuPicture[1] = new picture(usableArea, "image/menu/continue.png");
this->menuPicture[3] = new picture(usableArea, "image/menu/exit.png");
}
menu::~menu()
{
for (size_t i = 0; i < this->menuPictCount; i++) delete this->menuPicture[i];
delete[] menuPicture;
}
void menu::draw()
{
for (size_t i = 0; i < this->menuPictCount; i++) this->menuPicture[i]->draw();
}
void menu::posСorrection()
{
const int buttonsCount = this->menuPictCount - 1;
if (buttonsCount % 2 == 0)
{
int indexCenterOver = buttonsCount / 2;
int indexCenterUnder = indexCenterOver + 1;
this->menuPicture[indexCenterOver]->putCenterOver();
this->menuPicture[indexCenterUnder]->putCenterUnder();
for (size_t i = indexCenterOver - 1; i > 0; i--)
{
this->menuPicture[i]->putOverObj(*this->menuPicture[i + 1]);
}
for (size_t i = indexCenterUnder + 1; i <= buttonsCount; i++)
{
this->menuPicture[i]->putUnderObj(*this->menuPicture[i - 1]);
}
}
else
{
const int indexCenter = buttonsCount / 2 + 1;
this->menuPicture[indexCenter]->putCenter();
for (size_t i = indexCenter - 1; i > 0; i--)
{
this->menuPicture[i]->putOverObj(*this->menuPicture[i + 1]);
}
for (size_t i = indexCenter + 1; i <= buttonsCount; i++)
{
this->menuPicture[i]->putUnderObj(*this->menuPicture[i - 1]);
}
}
}
void menu::shineButton(sf::Color color)
{
/*for (size_t i = 0; i <= this->buttons.GetCount(); i++)
{
if (this->buttons.GetElement(i)->data.trackContainsCursor())
if (this->buttons.GetElement(i)->data.getColor() != color)
{
this->buttons.GetElement(i)->data.setColor(color);
}
if (!this->buttons.GetElement(i)->data.trackContainsCursor())
if (this->buttons.GetElement(i)->data.getColor() == color)
{
this->buttons.GetElement(i)->data.setColor(color);
}
}*/
} ```
[1]: https://i.stack.imgur.com/uNY8B.png
Instead of
picture* menuPicture[];
use
std::vector<std::unique_ptr<picture>> menuPicture;
And in menu constructor instead of doing this:
this->menuPicture[this->menuPictCount];
do this:
this->menuPicture.resize(this->menuPictCount);
Edit:
Of course remove also deletes from destructor. std::vector and std::unique_ptr will clean up after themselves.
If number of pictures in menu is constant (like in your constructor) you can change menuPicture declaration to:
std::array<std::unique_ptr<picture>, 4> menuPicture;
but then you can't call resize on it.
So i'm learning c++ and decided to try SDL out so I can get used to working with classes. The game is basically a space shooter game , so i wrote some code that permits the "shooting of bullets".The code works fine on my computer , the bullets travel from point X to point Y without a problem.When i tried to run the game on 2 different computers the "bullets" are very buggy (they disappear and reapper at random and such) .The rest of the game works fine. I tested the framerate on both computers and the fps is over 300
Does anyone know what causes this and how to solve it?
Here's some code (for the bullets) if you need it for some reason:
//LOAD BULLET IF FREE
if(bulletEnemyCooldown.getTicks() > bulletEnemyCooldownVar)
{
bulletEnemyCooldown.reset();
for (int i = 0; i < kShips; i++)
{
if(!evilShip[i].getIfDead())
{
for(int j=0; j<99; j++)
{
if (evilShip[i].getIfBulletFree(j))
{
evilShip[i].setKBullets(evilShip[i].getkBullets() + 1);
evilShip[i].setRectPos(evilShip[i].getPosX(),evilShip[i].getPosY(),j);
evilShip[i].setIfBulletFree(false,j);
break;
}
}
}
}
}
//CHANGE BULLET POS IF SLOT OCC AND RENDER
for (int i2 = 0; i2 <= kShips; i2++)
{
if(!evilShip[i2].getIfDead())
{
for(int j2 = 0; j2<evilShip[i2].getkBullets(); j2++)
{
if (evilShip[i2].getIfBulletFree(j2) == false)
{
evilShip[i2].setBulletRectY( evilShip[i2].getBulletRectY(j2) + bulletS,j2);
enemy_bullet_texture.render(gRenderer, evilShip[i2].getBulletRectX(j2), evilShip[i2].getBulletRectY(j2));
evilShip[i2].setBulletDis(evilShip[i2].getBulletDis(j2) + bulletS,j2);
}
}
}
}
//CHECK FOR ANY COLLISION AND FREE BULLET IF FOUND
for (int i = 0; i < kShips; i++)
{
for (int j = 0; j < evilShip[i].getkBullets(); j++)
{
if(!evilShip[i].getIfDead())
{
if (checkCollision(evilShip[i].getBulletPosRect(j), mainShip.getmCollider()))
{
evilShip[i].setIfBulletFree(true,j);
evilShip[i].setBulletDis(0,j);
evilShip[i].setKBullets( evilShip[i].getkBullets() - 1);
evilShip[i].setRectPos(0,0,j);
boolMainShipContact = true;
mainShip.curSetHP(mainShip.curGetHP() - evilShip[i].curGetATK());
kShipContact = i;
score -= rand()%(10 * currentLevel);
}
}
// FREE BULLET IF FOUND OFF SCREEN
if (evilShip[i].getBulletDis(j) > SCREEN_HEIGHT)
{
evilShip[i].setIfBulletFree(true,j);
evilShip[i].setBulletDis(0,j);
evilShip[i].setKBullets(evilShip[i].getkBullets() - 1);
}
}
}
I'm gonna add some abilities to random blocks, u know that drops down when you hit a random block. Like you get 2 balls or bigger paddle or slower ball speed.
I need help with writing the for loop and if-statement that can add some abilities to my block levels. Like 1 random ability on level 1 and so on. So when you hit 1 random block of like 20 blocks, that has my ability. It would drop down to the paddle like the original breakout game.
I was thinking of a switch, if one random block with ability is hit and using that switch and randomize it.
void PowerUp()
{
powerups.Add(abilityballs_rect);
powerups.Add(abilitylong_rect);
powerups.Add(abilityslow_rect);
}
-
List<Rectangle> block = new List<Rectangle>();
List<Rectangle> block2 = new List<Rectangle>();
List<Rectangle> block3 = new List<Rectangle>();
List<Rectangle> block4 = new List<Rectangle>();
List<Rectangle> block5 = new List<Rectangle>();
List<Rectangle> block6 = new List<Rectangle>();
List<Rectangle> powerups = new List<Rectangle>();
-
if (level == 1)
{
if (block.Count == 14 && block2.Count == 14)
{
spriteBatch.DrawString(spritefont2, "LEVEL " + level, new Vector2(252, 400), Color.White);
}
foreach (Rectangle g in block)
{
spriteBatch.Draw(block_texture, g, Color.LimeGreen);
}
foreach (Rectangle r in block2)
{
spriteBatch.Draw(block_texture, r, Color.IndianRed);
}
}
else if (level == 2)
{
if (block3.Count == 18 && block4.Count == 27)
{
spriteBatch.DrawString(spritefont2, "LEVEL " + level, new Vector2(246, 400), Color.White);
}
foreach (Rectangle b in block3)
{
spriteBatch.Draw(block_texture, b, Color.CornflowerBlue);
}
foreach (Rectangle y in block4)
{
spriteBatch.Draw(block_texture, y, Color.Yellow);
}
}
else if (level == 3)
{
if (block5.Count == 36 && block6.Count == 18)
{
spriteBatch.DrawString(spritefont2, "LEVEL " + level, new Vector2(246, 400), Color.White);
}
foreach (Rectangle o in block5)
{
spriteBatch.Draw(block_texture, o, Color.Orange);
}
foreach (Rectangle p in block6)
{
spriteBatch.Draw(block_texture, p, Color.HotPink);
}
}
-
void AddBlocks()
{
//LEVEL 1
for (int i = 1; i < 3; i++)
{
for (int f = 1; f < 8; f++)
{
block.Add(new Rectangle((f * 63) + 94, (i * 40) + 60, block_texture.Width, block_texture.Height));
}
}
for (int i = 1; i < 3; i++)
{
for (int g = 1; g < 8; g++)
{
block2.Add(new Rectangle((g * 63) + 94, (i * 40) + 40, block_texture.Width, block_texture.Height));
}
}
//LEVEL 2
for (int i = 1; i < 3; i++)
{
for (int j = 1; j < 10; j++)
{
block3.Add(new Rectangle((j * 63) + 34, (i * 200) - 60, block_texture.Width, block_texture.Height));
}
}
for (int i = 1; i < 10; i++)
{
for (int k = 1; k < 4; k++)
{
block4.Add(new Rectangle((k * 103) + 143, (i * 20) + 140, block_texture.Width, block_texture.Height));
}
}
//LEVEL 3
for (int i = 1; i < 7; i++)
{
for (int j = 1; j < 7; j++)
{
block5.Add(new Rectangle((j * 63) + 127, (i * 20) + 190, block_texture.Width, block_texture.Height));
}
}
for (int i = 1; i < 10; i++)
{
for (int k = 1; k < 3; k++)
{
block6.Add(new Rectangle((k * 443) - 317, (i * 20) + 160, block_texture.Width, block_texture.Height));
}
}
}
-
void DeleteBlocks()
{
if (level == 1)
{
for (int j = 0; j < block.Count; j++)
{
if (ball_rect.Intersects(block[j]))
{
ball_speed.Y *= -1;
points += 1;
block.RemoveAt(j);
if (points > highscore)
{
highscore = points;
}
}
}
for (int k = 0; k < block2.Count; k++)
{
if (ball_rect.Intersects(block2[k]))
{
ball_speed.Y *= -1;
points += 1;
block2.RemoveAt(k);
if (points > highscore)
{
highscore = points;
}
}
}
if (block.Count == 0 && block2.Count == 0)
{
level++;
StartValueBallPaddle();
Start = false;
}
}
else if (level == 2)
{
for (int l = 0; l < block3.Count; l++)
{
if (ball_rect.Intersects(block3[l]))
{
ball_speed.Y *= -1;
points += 1;
block3.RemoveAt(l);
if (points > highscore)
{
highscore = points;
}
}
}
for (int m = 0; m < block4.Count; m++)
{
if (ball_rect.Intersects(block4[m]))
{
ball_speed.Y *= -1;
points += 1;
block4.RemoveAt(m);
if (points > highscore)
{
highscore = points;
}
}
}
if (block3.Count == 0 && block4.Count == 0)
{
level++;
StartValueBallPaddle();
Start = false;
}
}
else if (level == 3)
{
for (int n = 0; n < block5.Count; n++)
{
if (ball_rect.Intersects(block5[n]))
{
ball_speed.Y *= -1;
points += 1;
block5.RemoveAt(n);
if (points > highscore)
{
highscore = points;
}
}
}
for (int o = 0; o < block6.Count; o++)
{
if (ball_rect.Intersects(block6[o]))
{
ball_speed.Y *= -1;
points += 1;
block6.RemoveAt(o);
if (points > highscore)
{
highscore = points;
}
}
}
}
}
You might want to encapsulate your block data into a class, containing the color, the position and powerup of the block.
You could have a method inside that would be called "AddPowerup()" or something, this method will be used to add a random (or specific) powerup to the block. You'll maybe need a getter for your powerup.
Now in your game, you would hold all the blocks of a level inside a list, or a 2d array, or any collection that suits you
Then, to apply powerup to random blocks in the level, you could do something like this (mostly pseudo code, so not tested) :
List<Block> blockList = CreateBlockLevel(1);
int randomIndex = new Random().Next(blockList.Length-1);
blockList[randomIndex].AddPowerup();
If you want to apply a powerup to multiple blocks, you can put that in a for-loop, but then you might want to check if the block has already a powerup or not.