EXC_BAD_ACCESS onTouchEnded when using Widget in Cocos2dx - c++

This is my code. I have layer 1 contains button 1 and layer 2 contains button 2. I'm using the UI to load the layers and button from Cocos Studio exported files. I added touch for 2 button, and write the touchEvent function below. However, when I test, sometimes, it causes the EXC_BAD_ACCESS onTouchEnded. Do you know why and how to fix this issue?
It seems similar with this issue
http://discuss.cocos2d-x.org/t/bug-ui-button-cant-delete-it-self/16282
Thank you very much
if (listener->onTouchEnded)
{
listener->onTouchEnded(*touchesIter, event); // EXC_BAD_ACCESS here
}
void FJPopupLayer::touchEvent(Ref *pSender, ui::Widget::TouchEventType type,
BUTTON_TAG button) {
switch (type) {
case ui::Widget::TouchEventType::BEGAN:
break;
case ui::Widget::TouchEventType::MOVED:
break;
case ui::Widget::TouchEventType::ENDED:
if (button == 1) {
// Remove the layer 2
// Add the layer 1
} else if (button == 2) {
// Remove the layer 1
// Add the layer 2
}
break;
case ui::Widget::TouchEventType::CANCELED:
break;
default:
break;
}
}

Related

Clueless about how to use switch

this is my very first post :)
I'm a graphic design student in my second year and we have to make code for business cards.
What I want is when I click with my mouse the background of the business card will change.
It worked with a boolean for two pictures.
But now I want it to work with four images.
Have asked the teacher for help and she sent me information about Switch.
But I have no idea where to put in my code and how to fill it in.
This is my code so far
String Instagram="#Famoys_Saz";
String quote = "Guess my passion ;)";
PFont font;
PImage bg;
PImage Snake2;
PImage snake3;
PImage snake4;
boolean click = true;
void setup() {
size(850, 550);
font = createFont("Galaxyfaceano-4yM9.ttf", 45);
textFont(font);
textAlign(CENTER);
bg = loadImage("Snake.jpg");
Snake2= loadImage ("Snake2.jpg");
click = true;
}
void draw() {
background(bg);
if (click == true ) {
image(bg, 0, 0);
} else {
image(Snake2, 0, 0);
}
text(Instagram, mouseX, mouseY);
text(quote, mouseY, mouseX, 05);
}
void mousePressed() {
click =! click;
}
and this is the code my teacher send me:
if( imageNumber == 1 ) {
} else if ( imageNumber == 2 ) {
} else {
}
Could someone help me out? I'm quite a beginner when it comes to coding.
it will look something like this:
switch( imageNumber ) {
case 1: // same as saying imageNumber == 1
//some code
break;
case 2: // same as saying imageNumber == 2
//some code here
break;
}
switch(imageNumber) {
case 1:
// do stuff
break;
case 2:
// do stuff
break;
case 3:
// do stuff
break;
case 4:
// do stuff
break;
default:
// if no case was selected, do this
}
Switches are easy to read and efficient, and some programmers prefers them to else if. Both are fine, as long as they are readable, but the switch has some unique particularities, like having to use break; between cases. The break; will exit the switch, else it would evaluate every other possible case (thus you're saving some execution time).
It happened to me in a robotic project to deliberately skip the break; statement so the robot would do "everything from this point on", but it's very uncommon and a source of many beginner's bugs to forget the break;.
Depending on the language, switches can evaluate different things, but the classics are integers and strings.
Have fun!

C++ How do I Handle all possible Player Movement inputs?

I am trying to clean up movement code I followed from a video tutorial series that was never finished. My intent is for the character to only ever be able to move on X or Y at any given time (so no diagonal). The character has direction facing to keep in mind.
My issue is the player can still press any key they want, or accidently press two keys at the same time.
Ex. if you move Up and make a right turn, accidentally press Right before letting go of Up.
Or if you press Up, press and let go Right to make a slight movement right while continuing to press Up, the player should continue to move up after letting go of Right without having to re-press Up. etc.
Just to make sure all possible input cases are handled intuitively.
EDIT: This is the code so far and I'm getting weird errors I don't know what's wrong
#pragma once
#include "../game.h"
#include "ECS.h"
#include "Components.h"
#include <list>
using namespace std;
class KeyboardController : public Component
{
public:
TransformComponent *transform;
SpriteComponent *sprite;
std::list<SDL_Event> keyDownList;
SDL_Event lastDirection;
void updateKeyState()
{
if (Game::event.type == SDLK_ESCAPE) {
Game::isRunning = false;
}
else if (Game::event.type == SDL_KEYDOWN) {
keyDownList.push_back(Game::event.key.keysym.sym);
}
else if (Game::event.type == SDL_KEYUP) {
keyDownList.remove(Game::event.key.keysym.sym);
}
}
void init() override
{
transform = &entity->getComponent<TransformComponent>();
sprite = &entity->getComponent<SpriteComponent>();
}
void update() override
{
void updateKeyState();
void updateMovement();
}
};
Severity Code Description Project File Line Suppression State
Error (active) E0304 no instance of overloaded function "std::list<_Ty, _Alloc>::push_back [with _Ty=SDL_Event, _Alloc=std::allocator]" matches the argument list Sandbox C:\file_path\KeyboardController.h 31
Severity Code Description Project File Line Suppression State
Error (active) E0415 no suitable constructor exists to convert from "SDL_Keycode" to "SDL_Event" Sandbox C:\file_path\KeyboardController.h 34
You should basically clean up your code by separating the logic between key events and player movement. So your update() method could look like this:
void update() override
{
updateKeyState();
updateMovement();
}
Since you want the player to move only vertically or horizontally (never diagonally), you have to store the key press order in a data structure that can be easily accessed. I think you could use a doubly-linked list:
std::list<SDL_Event> keyDownList;
and we should also store the last key pressed in order to restore the idle animation of the player:
SDL_Event lastDirection;
The updateKeyState() method should add or remove the key to/from the linked list. We should also check if the player wants to leave the game by pressing ESC:
void updateKeyState() {
if (Game::event.type == SDLK_ESCAPE) {
Game::isRunning = false;
} else if (Game::event.type == SDL_KEYDOWN) {
keyDownList.push_back(Game::event.key.keysym.sym);
} else if (Game::event.type == SDL_KEYUP) {
keyDownList.remove(Game::event.key.keysym.sym);
}
}
The updatePlayerMovement() method is where the magic happens. We should basically check which key was pressed first and update the player position accordingly. We also save the down key in the lastDirection field in order to use it when no key is pressed.
void updateMovement() {
// if any key is down
if (keyDownList.size() > 0) {
const SDL_Event downKey = keyDownList.front();
switch (downKey) {
case SDLK_w:
transform->velocity.y = -1;
transform->velocity.x = 0;
sprite->Play("BackWalk");
lastDirection = downKey;
break;
case SDLK_a:
transform->velocity.x = -1;
transform->velocity.y = 0;
sprite->Play("SideWalk");
sprite->spriteFlip = SDL_FLIP_HORIZONTAL;
lastDirection = downKey;
break;
case SDLK_s:
transform->velocity.y = 1;
transform->velocity.x = 0;
sprite->Play("FrontWalk");
lastDirection = downKey;
break;
case SDLK_d:
transform->velocity.x = 1;
transform->velocity.y = 0;
sprite->Play("SideWalk");
sprite->spriteFlip = SDL_FLIP_NONE;
lastDirection = downKey;
break;
}
} else {
// no key is down, handle idle situations
transform->velocity.x= 0;
transform->velocity.y = 0;
switch (lastDirection) {
case SDLK_w:
sprite->Play("BackIdle");
break;
case SDLK_a:
sprite->Play("SideIdle");
break;
case SDLK_s:
sprite->Play("FrontIdle");
break;
case SDLK_d:
sprite->Play("SideIdle");
break;
}
}
}
Note: I haven't tested this code because I don't have the code and structures from your game. So you may have to edit a piece here and there to make it work for you.

OpenGL - Left mouse click keeps removing my grid

I have created a drawGrid() function that draws a squared grid along my X and Y axis, which works fine. I have then created a menu() function (called in the main()), that toggles the grid on and off, here's the code for that:
void menu(int item)
{
switch (item)
{
case MENU_SWITCH_OFF_GRID:
{
if (gridActive == true)
{
gridActive = true;
}
}
break;
case MENU_SWITCH_ON_GRID:
{
if (gridActive == true)
{
gridActive = false;
}
}
break;
default:
{ /* Nothing */ }
break;
}
glutPostRedisplay();
return;
}
}
The menu switch works fine, as I have created a global variable called gridActive without a true or false value so it doesn't reset each time, that way it can be accessed in my display() function like so:
if (gridActive != true)
{
drawGrid();
gridActive = true;
}
All of this works just fine.
What's my issue?
My issue is, whenever I click the left mouse button, my grid disappears, which I don't want. So I've made a mouse() function like this:
case GLUT_LEFT_BUTTON: if (state == GLUT_DOWN)
{
exit(0); // this has been added to see if
// my program will exit!
}
break;
To test if my program exits when I click the left mouse, and it does.
So instead of using exit(0); what code can i put here so that my grid doesn't disappear when I click the left mouse button? Or is the issue beyond that?
UPDATE:
Here's the mouse function:
void mouse(int button, int state, int x, int y)
{
// these have simply been set-up for me to use
// in the future
switch (button)
{
case GLUT_LEFT_BUTTON: if (state == GLUT_DOWN)
{
}
break;
case GLUT_RIGHT_BUTTON: if (state == GLUT_DOWN)
{
}
break;
default: break;
}
}
Based on your code:
if (gridActive != true)
{
drawGrid();
gridActive = true;
}
You only draw the grid when gridActive is false. However, after every time you draw it, you set gridActive=true which will then stop it from being drawn.
Without more of your code, it's impossible to tell exactly what's going on, but these lines may not be doing what you think they are, and that may be causing some issues.
This never does anything.
if (gridActive == true)
{
gridActive = true;
}
This:
if (gridActive == true)
{
gridActive = false;
}
is the same as:
gridActive = false;
In order to tell what's going on, though, we need to know what happens when you click your mouse button when the exit call isn't there, but you didn't post that code yet.
Also, i don't quite know what you mean by:
I have created a global variable called gridActive without a true or false value so it doesn't reset each time
but it sounds like you made an uninitialized global variable and expect that it has some specific meaning because it's uninitialized?

SDL is sending a wrong controller index

I'm creating a simple game and I'm using SDL2 for handling inputs from controllers. The issue is that SDL is not giving me the correct index for the controller which causes my game to crash.
/receive the controller index given by SDL
int cIdx = evt.cdevice.which;
switch (evt.type)
{
case SDL_CONTROLLERAXISMOTION:
{
//.........
break;
}
case SDL_CONTROLLERBUTTONUP:
{
InputButton sender = InputButton(evt.cbutton.button);
controllerStates[cIdx]->SetButtonState(sender, false);
break;
}
case SDL_CONTROLLERBUTTONDOWN:
{
if (evt.cbutton.button != SDL_CONTROLLER_BUTTON_INVALID)
{
InputButton sender = InputButton(evt.cbutton.button);
controllerStates[cIdx]->SetButtonState(sender, true);
}
break;
}
case SDL_CONTROLLERDEVICEADDED:
{
if (SDL_IsGameController(cIdx))
{
SDL_GameController * controller = SDL_GameControllerOpen(cIdx);
AddController(controller);
}
break;
}
case SDL_CONTROLLERDEVICEREMOVED:
{
RemoveController(controllers[(cIdx)]);
break;
}
}
This works just fine when the user add the controller for the first time, SDL is sending me 0 as index in the SDL_CONTROLLERDEVICEADDED event and also 0 for the other events.
The problem is that if the user tries disconnect and reconnect the controller SDL send 0 as index in SDL_CONTROLLERDEVICEADDED event and 1 for the other events which causes the game to crash.
I can also make simple check if the index to avoid the crash but it will be useless since all controller events will be ignored.
Any help will be appreciated.
Thanks
According to SDL documentation, the index used on SDL_GameControllerOpen is not the index that will identify the controller in future events. So you need to use the joystick id instead.
switch (evt.type)
{
case SDL_CONTROLLERAXISMOTION:
{
//...
break;
}
case SDL_CONTROLLERBUTTONUP:
{
//Get the joystick id from the controller index
//....
break;
}
case SDL_CONTROLLERBUTTONDOWN:
{
//Get the joystick id from the controller index
//....
break;
}
case SDL_CONTROLLERDEVICEADDED:
{
if (SDL_IsGameController(cIdx))
{
SDL_GameController * controller = SDL_GameControllerOpen(cIdx);
SDL_Joystick* j = SDL_GameControllerGetJoystick(controller);
SDL_JoystickID joyId = SDL_JoystickInstanceID(j);
//Save the joystick id to used in the future events
AddController(controller);
}
break;
}
case SDL_CONTROLLERDEVICEREMOVED:
{
//Get the joystick id from the controller index
break;
}
}

exit from while loop

Here i am having function like this. problem i am facing while changing Set parameter section.
first: i could not able to change Set_parameter Window
Second: Since in my loop i am saying if none key pressed display clock.because of that when i enter into Section menu it directly bounce back to Main displaying clock. Is there any way, where i can stay menu section unless Exit/LEFT key pressed
This main function where i am calling my LCD_call Function
void loop()
{
int button;
while(( button = read_LCD_buttons()) != btnNONE)
{
lcd_call();digitalClockDisplay();
}
}
LCD_call being called here.
LCD_call
break command should break/exit the loop.
It could be that the if condition is not coming out to be true, for any input case.
Try debugging your code by placing a break point inside if.
if(button==btnSELECT)
{
break; // place your breakpoint here.
}
and check if your code satifies the if condition for any possible input.
This should work :
void lcd_call()
{
while ( (button = read_LCD_buttons()) != btnSELECT)
{
DS_Counter=Display_selection();
switch (DS_Counter)
{
case 1:
lcd.setCursor(0,0);
digitalClockDisplay();
timedBeep(shortBeep,1);
break;
case 2:
lcd.setCursor(0,0);
Display_angle();
timedBeep(shortBeep,1);
break;
case 3:
lcd.setCursor(0,0);
Display_coordinate();
timedBeep(shortBeep,1);
break;
case 4:
lcd.setCursor(0,0);
Display_Wind();
timedBeep(shortBeep,1);
break;
case 5:
break;
}
}
}
You have already given a condition in While loop. As soon as the condition is false, it will break the while loop