I have a cat game I have been working on in pygame that I am now writing in c++ SDL2 which are similar. But I have a weird specific problem. A variable in my level.cc class doesn't accrue with old += new in the move() function I am thinking that it is being set to 0 somewhere or my scope is off but I am just lost. I will post the files that are pertinent here and then link to my github as well. I appreciate your time and help.
The level.cc file:
void Level::move(int newx){
groundX += newx;
}
and the cat.cc file:
void Cat::move(int screenSize, Level l){
if((catmX + mVelX > 0) && (catmX + mVelX + (catwidth / 2) < (screenSize * .70))){
catmX += mVelX;
} else if(catmX + mVelX + (catwidth / 2) >= (screenSize * .70)){
l.move(CAT_VEL);
catmY += mVelY;
}
}
and the main:
string grndLoc = "src/grass.png";
Level level1(extra.loadTexture(grndLoc, extra.getRen()), extra.getHeight());
string backgroundImage = "src/sky.png";
SDL_Texture *bck = extra.loadTexture(backgroundImage, extra.getRen());
if(bck == nullptr){
extra.destroyer(bck);
extra.quitGame();
return 1;
}
SDL_Event e;
bool quit = false;
while(!quit){
while(SDL_PollEvent(&e)){
if(e.type == SDL_QUIT){
quit = true;
}
switch(e.key.keysym.sym){
case SDLK_ESCAPE:
quit = true;
break;
}
catplayer.handleEvent(e);
}
SDL_RenderClear(extra.getRen());
extra.renderTexture(bck, extra.getRen(), 0, 0, extra.getWidth(), extra.getHeight());
level1.rend(extra);
extra.renderTexture(catplayer.getTexture(), extra.getRen(), catplayer.getX(), catplayer.getY(), catplayer.getclip());
SDL_RenderPresent(extra.getRen());
catplayer.move(extra.getWidth(), level1);
https://github.com/ironsketch/catGamecpp
My teacher made mention that I was probably calling the constructor somewhere! I found that I was passing a copy of the level and not a pointer to the level!
void Cat::move(int screenSize, Level l){
So I changed it to
void Cat::move(int screenSize, Level *l){
I updated a few other things to reflect that I am now using a pointer and it's fixed! Thanks everyone who responded <3
Related
I have problem with running and debugging my program.
The thing is that when I run my program by 'Run' there is some bug, but when I'm trying to debug it, then it works fine.
I don't have a clue how to solve that.
There is link for short video: Video presenting problem
While running 2 sectors don't work, while debugging everything works fine.
I'm using CLion.
I find that different behavior happens in this function(it's only a piece of code, because whole project is quite big):
LevelSegmentCords* Space::findPlaceForBruteForce(int x, int y, int z) {
LevelSegmentCords *segmentCords = nullptr;
int i;
for(i=0;i<this->getHeight();i++){
int lastX=0,lastY=0;
int checkerX=0,checkerY=0;
do{
segmentCords = levels[i].findFreeSector(x,y,lastX,lastY);
if(segmentCords != nullptr){
segmentCords->setStartLevel(i);
for(int j=0;i+j<this->getHeight() && j<=z;j++){
if(!levels[i+j].isSectorFree(segmentCords->getX1(),
segmentCords->getY1(),
segmentCords->getX2()+1,
segmentCords->getY2()+1)){
checkerX = segmentCords->getX1();
checkerY = segmentCords->getY1();
}
}
if(checkerX != lastX || checkerY != lastY){
if(checkerX + 1 < this->x){
lastX = checkerX+1;
lastY = checkerY;
}else{
break;
}
}else{
return segmentCords;
}
}else{
break;
}
}while(true);
}
return nullptr;
}
This function should basically find place to put there cuboid.
Under my button class, I have this function that checks if the mouse is within the bounds of the button:
bool Button::isMouseOver(int mousePosX, int mousePosY) {
if (button.getPosition().x < mousePosX &&
button.getPosition().x + button.getSize().x > mousePosX &&
button.getPosition().y < mousePosY &&
button.getPosition().y + button.getSize().y > mousePosY) {
return true;
}
return false;
}
And then under my main cpp file I have this logic used to activate the function:
int mousePosX = sf::Mouse::getPosition().x;
int mousePosY = sf::Mouse::getPosition().y;
switch (Event.type) {
case sf::Event::Closed:
window.close();
case sf::Event::MouseButtonPressed:
if (btnPlay.isMouseOver(mousePosX, mousePosY)) {
std::cout << "True\n";
}
}
but for some reason, nothing happens. And I know that this can work, because I have the same exact code in one of my other games and it works fine.
Slightly off topic, you comment
And I know that this can work, because I have the same exact code in
one of my other games and it works fine.
triggered me to think You might want to consider generalizing this and making something like
bool IsInside(windowPos wp, windowSize ws, someOtherPos sop) {
if (wp.x < sop.X &&
wp.x + ws.x > sop.X &&
wp.y < sop.Y &&
wp.y + ws.y > sop.Y) {
return true;
}
return false;
}
bool Button::isMouseOver(Vector2i mousePos) {
return IsInside(getPosition(), getSize(), mousePos) ;
}
Note types in IsInside are not exact and might actually be the same ( Vector2i ).
This also makes testing easier for correctness and removes a source of errors with copied code.
I am using xlib to get keyboard input I want to simulate windows its getAsynckeystate() to check if a button is being pressed I tried using a timer to fix the result but its still broken. the function should always return true if 'z' is held down even if other keys are pressed or released at the same time (not working right now)
Code below
bool KeyboardState::keyPressed(Display* d, Window curFocus,int revert, Window root) {
XEvent ev;
XNextEvent(d, &ev);
clock_t startTime;
switch (ev.type) {
case FocusOut:
if (curFocus != root)
XSelectInput(d, curFocus, 0);
XGetInputFocus(d, &curFocus, &revert);
printf("New focus is %d\n", (int) curFocus);
if (curFocus == PointerRoot)
curFocus = root;
XSelectInput(d, curFocus, KeyReleaseMask | FocusChangeMask | KeyPressMask);
break;
case KeyPress:
ks = XLookupKeysym(&(ev.xkey), 0);
if (ks == XK_z) {
keyState = true;
startTime = clock();
}
break;
case KeyRelease:
if(ks == XK_z && startTime - clock() > 0){
ks = XLookupKeysym(&(ev.xkey), 0);
keyState = false;
}
}
return keyState;
}
n.m linked following function which is accepted as answer:
tronche.com/gui/x/xlib/input/XQueryKeymap.html
I wrote the following code snippet to help do keyboard shortcuts with multiple non-modifier keys e.g. super + up + right.
#include <X11/Xlib.h>
// Returns 0 if key is not down;
// A non-zero integer if it is down.
// targetString should be appropriate for XStringToKeysym.
int is_down(Display *dis, char *targetString)
{
char keys_return[32] = {0};
KeySym targetSym = XStringToKeysym(targetString);
KeyCode targetCode = XKeysymToKeycode(dis, targetSym);
int targetByte = targetCode / 8;
int targetBit = targetCode % 8;
int targetMask = 0x01 << targetBit;
XQueryKeymap(dis, keys_return);
return keys_return[targetByte] & targetMask;
}
I've posted a more complete example with compilation instructions on GitHub. You can find a complete list of key names in a file named X11/keysymdef.h; on my Arch computer it was at /usr/include/X11/keysymdef.h. I also found an example on the web as the second Google result for x11 keysymdef.
How can I call an if statement (or any other function) without calling it again, until it's finished executing? I have an update function that calls another function (in another class) but because it executes every update, the user doesn't get the time to actually complete the IF statements (the if statements rely on user input) so therefor it returns nothing or only the first part.
Code (where the update is):
public void Update(){
if(Mouse.isButtonDown(0)){
changeTile();
}
while(Keyboard.next()){
if(Keyboard.getEventKey() == Keyboard.KEY_RIGHT && Keyboard.getEventKeyState()){
moveIndex();
}
if(Keyboard.getEventKey() == Keyboard.KEY_LEFT && Keyboard.getEventKeyState()){
moveIndexBack();
}
}
}
changeTile function:
public void changeTile(){
boolean start = true;
if(start){
while(Mouse.next()){
if(Mouse.getEventButton() == 0 && Mouse.getEventButtonState()){
//system uses tileTypes because player textures are tiletypes itself, so in the end we can let them swim by changing tiletypes
int xCoord = (int) Math.floor(Mouse.getX() / 64);
int yCoord = (int) Math.floor((HEIGHT - Mouse.getY() - 1) / 64);
tileType tile1 = map[xCoord][yCoord].getType();
System.out.println("first tile is set to:" + tile1);
start = false;
}
}
}
if(!start){
while(Mouse.next()){
if(Mouse.getEventButton() == 0 && Mouse.getEventButtonState()){
int xCoord2 = (int) Math.floor(Mouse.getX() / 64);
int yCoord2 = (int) Math.floor((HEIGHT - Mouse.getY() - 1) / 64);
tileType tile2 = map[xCoord2][yCoord2].getType();
System.out.println("second tile is set to:" + tile2);
}
}
}
I got a warning on xcode 6.0.1 that I needed to update my project, so I did...
...but then I got issues with arc4random() % instead
Everything was working fine before this update, but now I get the following message:
"Thread 1: EXC_ARITHMETIC (code = EXC_1386_DIV, Subcode = 0x0) and the game crashes.
I tried with arc4random_uniform but the game seems to "pause" and nothing happens. What I mean is that I could see that it entered the if(bType == pt || bType == pl) statement but there is seems to "pause" and loop endlessly.
any suggestions?
-(void)placeInGrid:(CGPoint)place pt:(int)pt pl:(int)pl amount:(int)amountOfbricks{
CCLOG(#"BRICKS:placeInGrid");
//CCLOG(#"pt %d", pt);
//CCLOG(#"pl %d", pl);
int bType = arc4random() % amountOfbricks;
//int bType = arc4random_uniform(amountOfbricks);
if(bType == pt || bType == pl){
CCLOG(#"bType == pt || bType == pl");
[self placeInGrid:place pt:pt pl:pl amount:amountOfbricks];
return;
}
else{
CCLOG(#"else");
CCSpriteBatchNode * b = (CCSpriteBatchNode *)[theGame getChildByTag:kSSheet];
mySprite = [CCSprite spriteWithBatchNode:b rect:[self setBrickType:bType]];
[b addChild:mySprite z:1];
self.bricksType =bType;
[self.mySprite setPosition:place];
}
}
UPDATE:
the if-else statement below looks for saved data at the beginning of the game, to see if it´s a saved game or a new game.
The problem as it seems, after the project update is that the game thinks that there is already saved data and it goes to the first if statement ( if(gameData)), causing amountofbricks to be equal to 0, instead of going into the else statement where amountofbricks is equal to 4.
I don´t know how to solve this issue.
if ([[GameManager sharedGameManager] isContinuePressed] == NO && [[GameManager sharedGameManager] isNewPressed] == YES) {
if(gameData){
CCLOG(#"gameData && isContinuePressed == NO && isNewPressed == YES");
//Set the local instance of myobject to the object held in the gameState filler with the key "myObject"
level = 1;
[[GameManager sharedGameManager] setHScore:[decoder decodeIntegerForKey:#"HighScore"]];
highscore = [[GameManager sharedGameManager] ReturnHScore];
countTime = 300;
AmountOfBricks = [[GameManager sharedGameManager] ReturnAmountOfBricks];
BeginningOfGame = YES;
CCLOG(#"AmountOfBricks %d", AmountOfBricks);
}
else{
CCLOG(#"!gameData && isContinuePressed == NO && isNewPressed == YES");
if([[GameManager sharedGameManager]isThereASavedGame] ==YES){
CCLOG(#"isThereASavedGame == YES");
score = 0;
highscore = [[GameManager sharedGameManager] ReturnHScore];
level = 1;
countTime = 300;
AmountOfBricks = 4;
BeginningOfGame = YES;
CCLOG(#"AmountOfBricks %d", AmountOfBricks);
}
else{
CCLOG(#"isThereASavedGame == NO");
score = 0;
highscore = 0;
level = 1;
countTime = 300;
AmountOfBricks = 4;
BeginningOfGame = YES;
CCLOG(#"AmountOfBricks %d", AmountOfBricks);
}
}
}
UPDATE: I found the issue.
the issue was in my game manager.m file.
NSMutableData *gameData;
NSKeyedUnarchiver *decoder = nil;
NSString *documentPath = [documentsDirectory stringByAppendingPathComponent: #"gameState.dat"];
gameData = [NSData dataWithContentsOfFile:documentPath];//before the update, I as using this line. was working perfectly. after the update I got a warning on this line "incompatible pointer" and xcode recommended to update to the line below but the line below started to return a zero value. which caused the game to crash.
//gameData = [NSMutableData dataWithData:[NSData dataWithContentsOfFile:documentPath]];
I wager amountOfBricks is 0. You can't modulo by 0 like you can't divide by 0.