How do I move snake as intended in a snakeGame? [closed] - c++

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I actually posted one similar question but without any non working code. Now i've got some. So i want to make snake move in one direction(ex: UP) until i press the other button(DOWN, LEFT, RIGHT) where i would change direction to that.
However, i've got this piece of code where i commented out one of the problems, but now it only works partially in this manner:
If i press UP i can only press DOWN once more and than it keeps moving forever, if i press LEFT or RIGHT i can only press UP or DOWN and then alternate so DOWN or UP and it keeps moving in that direction forever
Here is the code:
void Game::ProcessEvents(){
sf::Event event;
while (myWindow.pollEvent(event)){
switch(event.type){
case sf::Event::KeyPressed : handlePlayerInput(event.key.code, true); break;
//case sf::Event::KeyReleased : handlePlayerInput(event.key.code, false); break;
case sf::Event::Closed : myWindow.close(); break;
}
}
}
void Game::handlePlayerInput(sf::Keyboard::Key key, bool isPressed){
if (key == sf::Keyboard::W || key == sf::Keyboard::Up) movingUp = isPressed;
else if (key == sf::Keyboard::S || key == sf::Keyboard::Down) movingDown = isPressed;
else if (key == sf::Keyboard::A || key == sf::Keyboard::Left) movingLeft = isPressed;
else if (key == sf::Keyboard::D || key == sf::Keyboard::Right) movingRight = isPressed;
}
void Game::update(){
sf::Vector2f movement(0.0f, 0.0f);
if (movingUp) { movingLeft = false; movingRight = false; movingDown = false; movement.y -= 0.1f;}
if (movingDown) { movingUp = false; movingLeft = false; movingRight = false; movement.y += 0.1f; }
if (movingLeft) { movingRight = false; movingUp = false; movingDown = false; movement.x -= 0.1f; }
if (movingRight) { movingLeft = false; movingDown = false; movingUp = false; movement.x += 0.1f; }
isColliding(movement);
}

Oof I'm not the biggest fan of how you're reading inputs and then transforming that to your movement object. For example, if movingUp is true, when will it ever be set to false? The answer is NEVER! There is no way for that to happen!
Instead, I'd make an enum with a single variable for the current direction of movement:
enum Dir { RIGHT, LEFT, UP, DOWN };
Dir curr_dir = RIGHT; // Start the game moving right
Now your handlePlayerInput logic can look like:
if (key == sf::Keyboard::W || key == sf::Keyboard::Up) curr_dir = UP;
else if (key == sf::Keyboard::S || key == sf::Keyboard::Down) curr_dir = DOWN;
else if (key == sf::Keyboard::A || key == sf::Keyboard::Left) curr_dir = LEFT;
else if (key == sf::Keyboard::D || key == sf::Keyboard::Right) curr_dir = RIGHT;
And the update logic can now be:
switch(curr_dir) {
case UP:
movement.y -= 0.1f;
break;
case DOWN:
movement.y += 0.1f;
break;
case RIGHT:
movement.x -= 0.1f;
break;
case LEFT:
movement.x += 0.1f;
break;
}

This is how I would do it:
Instead of having multiple bools have a single variable that denotes the direction. It can be an enum.
enum class Dir { up, down, left, right };
void Game::handlePlayerInput(sf::Keyboard::Key key, bool isPressed){
if (key == sf::Keyboard::W || key == sf::Keyboard::Up) direction = Dir::up;
else if (key == sf::Keyboard::S || key == sf::Keyboard::Down) direction = Dir::down;
else if (key == sf::Keyboard::A || key == sf::Keyboard::Left) direction = Dir::left;
else if (key == sf::Keyboard::D || key == sf::Keyboard::Right) direction = Dir::right;
Then use that variable to compute the movement
void Game::update(){
sf::Vector2f movement(0.0f, 0.0f);
if (direction == Dir::up) movement.y -= 0.1f;
else if (direction == Dir::down) movement += 0.1f;
else if (direction == Dir::left) movement.x -= 0.1f;
else if (direction == Dir::right) movement += 0.1f;
isColliding(movement);

Related

Box2d Player constantly jumping when using enum

I am trying to create a player that jumps and moves left and right.
At the moment, the player jumps infinitely on the spot, or moves infinitely left or right when the corresponding keys are pressed.
What do I need to add to this code to make the character stop jumping or moving once the key is released?
Here is the code so far:
void Character::update()
{
b2Vec2 pos = m_body->GetPosition();
setPosition(pos.x, pos.y);
float angle = m_body->GetAngle()* RAD2DEG;
setRotation(angle);
if (m_movingStates[LEFT])
{
m_body->ApplyLinearImpulseToCenter(b2Vec2(-0.03, 0.0f), true);
}
if (m_movingStates[RIGHT])
{
m_body->ApplyLinearImpulseToCenter(b2Vec2(0.03, 0.0f), true);
}
if (m_movingStates[JUMP] && m_sit)
{
m_body->ApplyLinearImpulseToCenter(b2Vec2(0.f, -0.1f), true);
}
}
void Character::onKeyPress(sf::Event event)
{
if (event.key.code == sf::Keyboard::Left)m_movingStates[LEFT] = true;
if (event.key.code == sf::Keyboard::Right)m_movingStates[RIGHT] = true;
if (event.key.code == sf::Keyboard::Space)m_movingStates[JUMP] = true;
}
void Character::onKeyRelease(sf::Event event)
{
if (event.type == sf::Event::KeyReleased && event.key.code == sf::Keyboard::Left) m_movingStates[LEFT] = false;
if (event.type == sf::Event::KeyReleased && event.key.code == sf::Keyboard::Right) m_movingStates[RIGHT] = false;
if (event.type == sf::Event::KeyReleased && event.key.code == sf::Keyboard::Space) m_movingStates[JUMP] = false;
}

Strange behavior spotted c++ sdl2

Using sdl2 I managed to construct "soon-to-be-spaghetti" classes for a game. However when it came to using a function of a class I stumble upon this weirdness.
class Player{
public:
Player();
const SDL_Rect *getPositionPtr() const { return &position; }
const SDL_Rect * getClip(){ return &clip; }
void eventHandle(SDL_Event & e);
void move();
private:
SDL_Rect position;
SDL_Rect clip;
float velocity;
bool leftkeydown;
bool rightkeydown;
};
Player::Player(){
position = {100, 300, 64, 64};
clip = {0, 0, 64, 64};
velocity = 0.3;
leftkeydown = false;
rightkeydown = false;
}
void Player::eventHandle(SDL_Event & e){
if( e.type == SDL_KEYDOWN && e.key.repeat == 0 ){
switch( e.key.keysym.sym ){
case SDLK_a:
leftkeydown = true;
break;
case SDLK_d:
rightkeydown = true;
break;
}
}
else if( e.type == SDL_KEYUP && e.key.repeat == 0 ){
//Adjust the velocity
switch( e.key.keysym.sym ){
case SDLK_a:
leftkeydown = false;
break;
case SDLK_d:
rightkeydown = false;
break;
}
}
}
void Player::move(){
if(leftkeydown) position.x -= velocity;
if(rightkeydown) position.x += velocity; // <----- problem here
}
leftkeydown seems to work as expected but rightkeydown doesn't do anything to the position.x variable.
Any ideas why it is not incrementing?
as #keltar commended it happens because at int + (float < 0) the int stays the same because it converts the result (100.3) from float to int (100) (thats because one of the values is int) so the position x will stay the same unless you make the velocity int or bigger than 0.

How to switch back and forth between two different sections on a sprite sheet while user still holds a key using SFML

So my only goal here is to move the sprite left and right, and while the sprite is moving, I want to switch between two different parts of my sprite sheet every half a second.
I've tried everything I could think of so I left it working and without only the implementation of the needed feature. (EDIT: I've changed it in an attempt to try to follow advice given by another user) I've looked online, but nothing I could find answered my question as far as I could tell. I'm sure there's something I'm overlooking and that it is quite simple, but that's why I need your input.
The third parts of the sprite sheet I want to use is at x = 800, animations facing left are on top at y = 0, and the animations facing right are on bottom at y = 600
Here is the sprite sheet I am using
The first ones are for standing still, and the second two on either row are the ones I want to switch between while "walking"
At any rate, here is my code:
#include "pch.h"
#include <iostream>
#include "SFML/Graphics.hpp"
#include <random>
#include <unordered_map>
enum State
{
Walking,
Standing
};
enum Direction
{
Left,
Right
};
int main(int argc, char ** argv)
{
/* Gregory */
sf::Texture GregorySpriteSheet_T;
GregorySpriteSheet_T.loadFromFile("Images/GregorySpriteSheet.png");
sf::IntRect GregorySpriteRect(0, 600, 400, 600);
sf::Sprite Gregory(GregorySpriteSheet_T, GregorySpriteRect);
sf::RenderWindow renderWindow(sf::VideoMode(1600,800), "SFML 2 Demo");
sf::Event event;
sf::Time timePerFrame = sf::seconds(1.0f / 60.0f);
sf::Clock deltaClock;
sf::Time timeSinceLastUpdate = sf::Time::Zero;
State isWalking{ Standing };
sf::Clock walkClock;
Direction direction = Right;
/* RENDER WINDOW LOOP */
while (renderWindow.isOpen())
{
sf::Time deltaTime = deltaClock.restart();
timeSinceLastUpdate += deltaTime;
while (timeSinceLastUpdate >= timePerFrame)
{
timeSinceLastUpdate -= timePerFrame;
while (renderWindow.pollEvent(event))
{
if (event.type == sf::Event::EventType::Closed || sf::Keyboard::isKeyPressed(sf::Keyboard::Escape))
{
renderWindow.close();
}
if (event.type == sf::Event::EventType::KeyPressed)
{
if (event.key.code == sf::Keyboard::Right)
{
isWalking = Walking;
direction = Right;
}
}
if (event.type == sf::Event::EventType::KeyReleased)
{
if (event.key.code == sf::Keyboard::Right)
{
isWalking = Standing;
}
}
if (event.type == sf::Event::EventType::KeyPressed)
{
if (event.key.code == sf::Keyboard::Left)
{
isWalking = Walking;
direction = Left;
}
}
if (event.type == sf::Event::EventType::KeyReleased)
{
if (event.key.code == sf::Keyboard::Left)
{
isWalking = Standing;
}
}
}
if (isWalking == Walking)
{
if (direction == Right)
GregorySpriteRect.top = 600;
if (direction == Left)
GregorySpriteRect.top = 0;
if (GregorySpriteRect.left == 0)
GregorySpriteRect.left = 400;
if ((int(walkClock.getElapsedTime().asSeconds() / 1.5f) % 2) == 1)
{
if (GregorySpriteRect.left == 400)
GregorySpriteRect.left == 800;
if (GregorySpriteRect.left == 800)
GregorySpriteRect.left == 400;
walkClock.restart();
}
}
{
using kb = sf::Keyboard;
if (kb::isKeyPressed(kb::Right))
{
Gregory.move(400 * timePerFrame.asSeconds(), 0.0f);
direction = Right;
isWalking = Walking;
}
if (kb::isKeyPressed(kb::Left))
{
Gregory.move(-400 * timePerFrame.asSeconds(), 0.0f);
direction = Left;
isWalking = Walking;
}
if (kb::isKeyPressed(kb::Right) && kb::isKeyPressed(kb::Left))
{
isWalking = Standing;
}
}
if (isWalking == Standing)
{
GregorySpriteRect.left = 0;
if (direction == Right)
GregorySpriteRect.top = 600;
if (direction == Left)
GregorySpriteRect.top = 0;
}
}
Gregory.setTextureRect(GregorySpriteRect);
renderWindow.clear();
renderWindow.draw(Gregory);
renderWindow.display();
}
/* END RENDER WINDOW LOOP */
}
Here is one suggestion, but there are plenty of alternatives:
First, rewrite your event handling slightly such that you can differentiate between the first time a key is held and subsequent times. A simple way is to have an enum State { Standing, Walking } and set it to the appropriate value in your key handler (eg "not walking and key is held? set state to walking")
Then, when the player starts walking, (re)start a "walk" clock.
Finally, when you are actually rendering your player, check this clock and divide the expired time since walking by your walking period (this determines how long one of the walking frames should be held). If there were an even number of such walking periods, use the left walking sprite, otherwise the right walking sprite.
This technique easily generalizes to larger sets of walking frames, of course.
So for anybody that winds up here in the future, I was missing a vital line:
Gregory.setTextureRect(GregorySpriteRect);
Either in my "if" statement for the clock under the "if (isWalking == Walking)", or under it (like I've done here). Pasted the full code below. Works for both directions now. Not sure how optimal this is but if you're an amateur like me this should help.
Also mind that I've reverted back some of the changes suggested from Botje's answer. Although I must credit him for helping me very much with the recommendation of using enum's for Walking and Standing, as well as direction. I also used a ">" operator rather than the "==" operator as suggested by my professor due to rounding errors of float point variables.
Cheers!
#include "pch.h"
#include <iostream>
#include "SFML/Graphics.hpp"
#include <random>
#include <unordered_map>
enum State
{
Walking,
Standing
};
enum Direction
{
Left,
Right
};
int main(int argc, char ** argv)
{
/* Gregory */
sf::Texture GregorySpriteSheet_T;
GregorySpriteSheet_T.loadFromFile("Images/GregorySpriteSheet.png");
sf::IntRect GregorySpriteRect(0, 600, 400, 600);
sf::Sprite Gregory(GregorySpriteSheet_T, GregorySpriteRect);
sf::RenderWindow renderWindow(sf::VideoMode(1600,800), "SFML 2 Demo");
sf::Event event;
sf::Time timePerFrame = sf::seconds(1.0f / 60.0f);
sf::Clock deltaClock;
sf::Time timeSinceLastUpdate = sf::Time::Zero;
State isWalking{ Standing };
sf::Clock walkClock;
Direction direction = Right;
/* RENDER WINDOW LOOP */
while (renderWindow.isOpen())
{
sf::Time deltaTime = deltaClock.restart();
timeSinceLastUpdate += deltaTime;
while (timeSinceLastUpdate >= timePerFrame)
{
timeSinceLastUpdate -= timePerFrame;
while (renderWindow.pollEvent(event))
{
if (event.type == sf::Event::EventType::Closed || sf::Keyboard::isKeyPressed(sf::Keyboard::Escape))
{
renderWindow.close();
}
if (event.type == sf::Event::EventType::KeyPressed)
{
if (event.key.code == sf::Keyboard::Right)
{
isWalking = Walking;
direction = Right;
GregorySpriteRect.top = 600;
}
}
if (event.type == sf::Event::EventType::KeyReleased)
{
if (event.key.code == sf::Keyboard::Right)
{
isWalking = Standing;
}
}
if (event.type == sf::Event::EventType::KeyPressed)
{
if (event.key.code == sf::Keyboard::Left)
{
isWalking = Walking;
direction = Left;
GregorySpriteRect.top = 0;
}
}
if (event.type == sf::Event::EventType::KeyReleased)
{
if (event.key.code == sf::Keyboard::Left)
{
isWalking = Standing;
}
}
}
if (isWalking == Walking)
{
if (direction == Right)
GregorySpriteRect.top = 600;
else if (direction == Left)
GregorySpriteRect.top = 0;
else
GregorySpriteRect.top = 600;
if (GregorySpriteRect.left == 0)
GregorySpriteRect.left = 400;
if (walkClock.getElapsedTime().asSeconds() > 0.5f)
{
if (GregorySpriteRect.left == 400)
GregorySpriteRect.left = 800;
else if (GregorySpriteRect.left == 800)
GregorySpriteRect.left = 400;
else
GregorySpriteRect.left += 0;
walkClock.restart();
}
Gregory.setTextureRect(GregorySpriteRect);
}
{
using kb = sf::Keyboard;
if (kb::isKeyPressed(kb::Right))
{
Gregory.move(400 * timePerFrame.asSeconds(), 0.0f);
direction = Right;
}
if (kb::isKeyPressed(kb::Left))
{
Gregory.move(-400 * timePerFrame.asSeconds(), 0.0f);
direction = Left;
}
if (kb::isKeyPressed(kb::Right) && kb::isKeyPressed(kb::Left))
{
isWalking = Standing;
direction = Right;
}
}
if (isWalking == Standing)
{
GregorySpriteRect.left = 0;
if (direction == Right)
GregorySpriteRect.top = 600;
if (direction == Left)
GregorySpriteRect.top = 0;
}
}
Gregory.setTextureRect(GregorySpriteRect);
renderWindow.clear();
renderWindow.draw(Gregory);
renderWindow.display();
}
/* END RENDER WINDOW LOOP */
}

Handling multiple keypressess at the same time in SDL

I'm making a simple top down 2D shooter, where you move with WASD and shoot in the direction you're looking at with space. I can move and shoot just fine, but I can't do them both at the same time. For example if I'm shooting and start moving, my character will stop shooting until I release and press space again, and if I then start moving in another direction I have to release and press space again.
Here's my main method:
int main(int argc, char* args[])
{
if (!init())
{
log("Failed to initialize!\n");
}
else
{
log("Initialized SDL and SDL subsystems. \nLoading assets:\n");
if (!loadAssets())
{
printf("Failed to load assets!\n");
}
else
{
log("All assets loaded successfully.\n");
bool running = true;
SDL_Event e;
std::vector<Shot> shots;
LTimer shotTimer;
float cooldown = 250.0f;
float previousCooldown = 0.0f;
Player player;
log("Game running.\n");
shotTimer.start();
while (running)
{
while (SDL_PollEvent(&e) != 0)
{
if (e.type == SDL_QUIT)
{
log("SDL_QUIT event triggered.\n");
running = false;
}
else if (e.type == SDL_KEYDOWN)
{
switch (e.key.keysym.sym)
{
case SDLK_ESCAPE:
{
running = false;
break;
}
}
}
player.handleEvent(e);
if (SDL_GetTicks() - previousCooldown > cooldown)
{
previousCooldown = SDL_GetTicks();
shots = shoot(e, player, shots);
}
}
player.move();
for (int i = 0; i < shots.size(); i++)
{
shots[i].move();
}
/*if (shotTimer.getTicks() >= cooldown)
shotTimer.restart();*/
SDL_SetRenderDrawColor(renderer, 0xff, 0xff, 0xff, 0xff);
SDL_RenderClear(renderer);
background.render(0, 0);
for (int i = 0; i < shots.size(); i++)
{
shots[i].render();
}
player.render();
SDL_RenderPresent(renderer);
}
}
}
close();
return 0;
}
Here's my shoot() function, which is probably what's causing this:
std::vector<Shot> shoot(SDL_Event& e, Player player, std::vector<Shot> shots)
{
bool shoot = false;
if (e.type = SDL_KEYDOWN && e.key.repeat == 1)
{
switch (e.key.keysym.sym)
{
case SDLK_SPACE:
{
shoot = true;
break;
}
}
}
else if (e.type = SDL_KEYUP && e.key.repeat == 1)
{
switch (e.key.keysym.sym)
{
case SDLK_SPACE:
{
shoot = false;
break;
}
}
}
if (shoot)
{
Shot newShot(player.getDir(), player);
shots.push_back(newShot);
}
return shots;
}
And this is how I move the player
void Player::handleEvent(SDL_Event& e)
{
if (e.type == SDL_KEYDOWN && e.key.repeat == 0)
{
switch (e.key.keysym.sym)
{
case SDLK_w: mVelY -= PLAYER_VEL; mDir = 0; break;
case SDLK_s: mVelY += PLAYER_VEL; mDir = 1; break;
case SDLK_d: mVelX += PLAYER_VEL; mDir = 2; break;
case SDLK_a: mVelX -= PLAYER_VEL; mDir = 3; break;
}
}
else if (e.type == SDL_KEYUP && e.key.repeat == 0)
{
switch (e.key.keysym.sym)
{
case SDLK_w: mVelY += PLAYER_VEL; break;
case SDLK_s: mVelY -= PLAYER_VEL; break;
case SDLK_d: mVelX -= PLAYER_VEL; break;
case SDLK_a: mVelX += PLAYER_VEL; break;
}
}
}
Separate your event polling from the rest of the game logic.
Poll all events once per frame in a separate function and store the state of the keystates into an array. Then, when you need the state, simply check the array.
You can also use SDL_GetKeyboardState to sample the surrent state of the keys, without having to handle the key events yourself.

Allegro pong collision problems

I have just recently started working with allegro 5 and decided to start with a basic pong game. I found one and decided to add some extras to it. After adding two more paddles and the needed variables and controls, I copied and pasted the collision code from the original two and added the needed variables. However, if I move the new paddles from the originals, they no longer bounce off the ball. The code is huge I know, but I have no idea whats causing the problem.
`
#include <stdio.h>
#include <cstdlib>
#include <sstream>
#include <allegro5/allegro.h>
#include <allegro5/allegro_primitives.h>
#include <allegro5/allegro_color.h>
#include <allegro5/allegro_font.h>
#include <allegro5/allegro_ttf.h>
/* constants and definitions */
const int SCREEN_W = 960;
const int SCREEN_H = 720;
const float FPS = 60;
const int paddle_height = 96;
const int paddle_width = 16;
const int bouncer_size = 16;
enum MYKEYS{
KEY_UP,KEY_DOWN,KEY_W,KEY_S,KEY_E,KEY_D,KEY_O,KEY_L
};
/* functions */
void draw_paddle(float x,float y){
// fill
al_draw_filled_rounded_rectangle(x,y,x+paddle_width,y+paddle_height,3,3,al_color_html("729fcf"));
// outline
al_draw_rounded_rectangle(x,y,x+paddle_width,y+paddle_height,3,3,al_color_html("b5edff"),1.0);
// shine
al_draw_filled_rounded_rectangle(x,y,x+paddle_width/2,y+paddle_height-10,3,3,al_color_html("8abbef"));
}
void draw_ball(float x,float y){
// fill
al_draw_filled_circle(x,y,bouncer_size,al_color_html("6be97d"));
// shadow
al_draw_filled_circle(x+bouncer_size/4,y+bouncer_size/4,bouncer_size/3*2,al_color_html("59ce76"));
// shine
al_draw_filled_circle(x-bouncer_size/3,y-bouncer_size/3,bouncer_size/4,al_color_html("9bffaa"));
}
void draw_score(int l,int r){
std::ostringstream ostr;
ostr << l;
std::ostringstream ostr1;
ostr1 << r;
ALLEGRO_FONT *font = al_load_font("arial.ttf",72,0);
al_draw_filled_rectangle(SCREEN_W/2-5,SCREEN_H,SCREEN_W/2+5,-SCREEN_H,al_color_html("ffffff"));
al_draw_text(font,al_color_html("ffffff"),SCREEN_W/2-50,0,ALLEGRO_ALIGN_CENTRE,ostr.str().c_str());
al_draw_text(font,al_color_html("ffffff"),SCREEN_W/2+50,0,ALLEGRO_ALIGN_CENTER,ostr1.str().c_str());
al_destroy_font(font);
}
int main(){
ALLEGRO_DISPLAY *display = NULL;
ALLEGRO_EVENT_QUEUE *event_queue = NULL;
ALLEGRO_TIMER *timer = NULL;
ALLEGRO_BITMAP *right_paddle = NULL;
ALLEGRO_BITMAP *left_paddle = NULL;
ALLEGRO_BITMAP *right_sub_paddle = NULL;
ALLEGRO_BITMAP *left_sub_paddle = NULL;
ALLEGRO_BITMAP *bouncer = NULL;
float right_paddle_x =(SCREEN_W*4/5)-(paddle_width/2.0);
float right_paddle_y =(SCREEN_H/2.0)-(paddle_height/2.0);
float left_paddle_x =(SCREEN_W*1/5)-(paddle_width/2.0);
float left_paddle_y =(SCREEN_H/2.0)-(paddle_height/2.0);
float right_sub_paddle_x = (SCREEN_W*4/5)-(paddle_width/2.0)-100;
float right_sub_paddle_y =(SCREEN_H/2.0)-(paddle_height/2.0);
float left_sub_paddle_x = (SCREEN_W*1/5)-(paddle_width/2.0)+100;
float left_sub_paddle_y = (SCREEN_H/2.0)-(paddle_height/2.0);
float bouncer_x = SCREEN_W/2.0-bouncer_size/2.0;
float bouncer_y = SCREEN_H/2.0-bouncer_size/2.0;
float bouncer_dx = 8.0,bouncer_dy = -8.0;
float paddle_speed = 8.0;
bool key[8] = {false,false,false,false,false,false,false,false};
bool redraw = true;
bool doexit = false;
bool pause = false;
int left_score = 0;
int right_score = 0;
if(!al_init()){
fprintf(stderr,"failed to initialized allegro\n");
return -1;
}
if(!al_install_keyboard()){
fprintf(stderr,"failed to install keyboard\n");
return -1;
}
al_init_primitives_addon();
al_init_font_addon();
al_init_ttf_addon();
al_set_new_display_option(ALLEGRO_SAMPLE_BUFFERS,1,ALLEGRO_SUGGEST);
al_set_new_display_option(ALLEGRO_SAMPLES,4,ALLEGRO_SUGGEST);
//initialize display(w,h)
display = al_create_display(SCREEN_W,SCREEN_H);
if(!display){
fprintf(stderr,"failed to create display\n");
return -1;
}
timer = al_create_timer(1.0/FPS);
if(!timer){
fprintf(stderr,"failed to create timer\n");
return -1;
}
right_paddle = al_create_bitmap(paddle_width,paddle_height);
if(!right_paddle){
fprintf(stderr,"failed to create right paddle bitmap\n");
return -1;
}
left_paddle = al_create_bitmap(paddle_width,paddle_height);
if(!left_paddle){
fprintf(stderr,"failed to create left paddle bitmap\n");
return -1;
}
right_sub_paddle = al_create_bitmap(paddle_width,paddle_height);
if(!right_sub_paddle){
fprintf(stderr,"failed to create right sub paddle bitmap\n");
return -1;
}
left_sub_paddle = al_create_bitmap(paddle_width,paddle_height);
if(!left_sub_paddle){
fprintf(stderr,"failed to create left sub paddle bitmap\n");
return -1;
}
bouncer = al_create_bitmap(bouncer_size,bouncer_size);
if(!bouncer){
fprintf(stderr,"failed to create bouncer bitmap\n");
return -1;
}
al_set_target_bitmap(left_paddle);
al_clear_to_color(al_map_rgb(0,255,0));
al_set_target_bitmap(right_paddle);
al_clear_to_color(al_map_rgb(0,255,0));
al_set_target_bitmap(left_sub_paddle);
al_clear_to_color(al_map_rgb(0,255,0));
al_set_target_bitmap(right_sub_paddle);
al_clear_to_color(al_map_rgb(0,255,0));
al_set_target_bitmap(bouncer);
al_clear_to_color(al_map_rgb(0,0,255));
al_set_target_bitmap(al_get_backbuffer(display));
event_queue = al_create_event_queue();
if(!event_queue){
fprintf(stderr,"failed to create event queue\n");
return -1;
}
al_register_event_source(event_queue,al_get_display_event_source(display));
al_register_event_source(event_queue,al_get_timer_event_source(timer));
al_register_event_source(event_queue,al_get_keyboard_event_source());
al_clear_to_color(al_map_rgb(0,0,0));
al_flip_display();
al_start_timer(timer);
while(!doexit){
ALLEGRO_EVENT ev;
al_wait_for_event(event_queue,&ev);
if(ev.type == ALLEGRO_EVENT_TIMER && !pause){
//logic for moving the paddles on input
if(key[KEY_UP] && right_paddle_y >= 4.0){
right_paddle_y -= paddle_speed;
}
if(key[KEY_DOWN] && right_paddle_y <= SCREEN_H-paddle_height-4.0){
right_paddle_y += paddle_speed;
}
if(key[KEY_W] && left_paddle_y >= 4.0){
left_paddle_y -= paddle_speed;
}
if(key[KEY_S] && left_paddle_y <= SCREEN_H-paddle_height-4.0){
left_paddle_y += paddle_speed;
}
if(key[KEY_E] && left_sub_paddle_y >= 4.0){
left_sub_paddle_y -= paddle_speed;
}
if(key[KEY_D] && left_sub_paddle_y <= SCREEN_H-paddle_height-4.0){
left_sub_paddle_y += paddle_speed;
}
if(key[KEY_O] && right_sub_paddle_y >= 4.0){
right_sub_paddle_y -= paddle_speed;
}
if(key[KEY_L] && right_sub_paddle_y <= SCREEN_H-paddle_height-4.0){
right_sub_paddle_y += paddle_speed;
}
//logic for the bouncer
if(bouncer_x < 0 || bouncer_x > SCREEN_W-bouncer_size){
if(bouncer_x < 0){
left_score += 1;
}else if(bouncer_x > SCREEN_W-bouncer_size){
right_score += 1;
}
paddle_speed = 8.0;
bouncer_x = SCREEN_W/2.0-bouncer_size/2.0;
bouncer_y = SCREEN_H/2.0-bouncer_size/2.0;
bouncer_dx = -bouncer_dx;
bouncer_dy = -bouncer_dx;
}
if(bouncer_y < 0 || bouncer_y > SCREEN_H-bouncer_size){
bouncer_dy = -bouncer_dy;
}
if(bouncer_x == left_paddle_x+(paddle_width/1.0)){
if(bouncer_y >= left_paddle_y+paddle_height || bouncer_y+bouncer_size < left_paddle_y){
}else{
paddle_speed += 1;
bouncer_dx = -bouncer_dx;
}
}
if(bouncer_x == right_paddle_x-(paddle_width/2.0)){
if(bouncer_y >= right_paddle_y+paddle_height || bouncer_y+bouncer_size < right_paddle_y){
}else{
paddle_speed += 1;
bouncer_dx = -bouncer_dx;
}
}
if(bouncer_x == left_sub_paddle_x+(paddle_width/1.0)){
if(bouncer_y >= left_sub_paddle_y+paddle_height || bouncer_y+bouncer_size < left_sub_paddle_y){
}else{
paddle_speed +=1;
bouncer_dx = -bouncer_dx;
}
}
if(bouncer_x == right_sub_paddle_x+(paddle_width/1.0)){
if(bouncer_y >= right_sub_paddle_y+paddle_height || bouncer_y+bouncer_size < right_sub_paddle_y){
}else{
paddle_speed +=1;
bouncer_dx = -bouncer_dx;
}
}
bouncer_x += bouncer_dx;
bouncer_y += bouncer_dy;
redraw = true;
}else if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE){
break;
}else if(ev.type == ALLEGRO_EVENT_KEY_DOWN){
switch(ev.keyboard.keycode){
case ALLEGRO_KEY_UP:
key[KEY_UP] = true;
break;
case ALLEGRO_KEY_DOWN:
key[KEY_DOWN] = true;
break;
case ALLEGRO_KEY_W:
key[KEY_W] = true;
break;
case ALLEGRO_KEY_S:
key[KEY_S] = true;
break;
case ALLEGRO_KEY_E:
key[KEY_E] = true;
break;
case ALLEGRO_KEY_D:
key[KEY_D] = true;
break;
case ALLEGRO_KEY_O:
key[KEY_O] = true;
break;
case ALLEGRO_KEY_L:
key[KEY_L] = true;
break;
}
}else if(ev.type == ALLEGRO_EVENT_KEY_UP){
switch(ev.keyboard.keycode){
case ALLEGRO_KEY_UP:
key[KEY_UP] = false;
break;
case ALLEGRO_KEY_DOWN:
key[KEY_DOWN] = false;
break;
case ALLEGRO_KEY_W:
key[KEY_W] = false;
break;
case ALLEGRO_KEY_S:
key[KEY_S] = false;
break;
case ALLEGRO_KEY_E:
key[KEY_E] = false;
break;
case ALLEGRO_KEY_D:
key[KEY_D] = false;
break;
case ALLEGRO_KEY_O:
key[KEY_O] = false;
break;
case ALLEGRO_KEY_L:
key[KEY_L] = false;
break;
case ALLEGRO_KEY_ESCAPE:
doexit = true;
break;
case ALLEGRO_KEY_P:
if(pause){
pause = false;
}else{
pause = true;
}
break;
}
}
if(redraw && al_is_event_queue_empty(event_queue)){
redraw = false;
al_clear_to_color(al_map_rgb(0,0,0));
draw_score(right_score,left_score);
draw_paddle(right_sub_paddle_x,right_sub_paddle_y);
draw_paddle(left_sub_paddle_x,left_sub_paddle_y);
draw_paddle(right_paddle_x,right_paddle_y);
draw_paddle(left_paddle_x,left_paddle_y);
draw_ball(bouncer_x,bouncer_y);
//al_draw_bitmap(right_paddle,right_paddle_x,right_paddle_y,0);
//al_draw_bitmap(left_paddle,left_paddle_x,left_paddle_y,0);
//al_draw_bitmap(right_sub_paddle,right_sub_paddle_x,right_sub_paddle_y,0);
//al_draw_bitmap(left_sub_paddle,left_sub_paddle_x,left_sub_paddle_y,0);
//al_draw_bitmap(bouncer,bouncer_x,bouncer_y,0);
al_flip_display();
}
}
al_destroy_bitmap(bouncer);
al_destroy_bitmap(right_paddle);
al_destroy_bitmap(left_paddle);
al_destroy_bitmap(right_sub_paddle);
al_destroy_bitmap(left_sub_paddle);
al_destroy_timer(timer);
al_destroy_display(display);
al_destroy_event_queue(event_queue);
return 0;
}`
Any help is greatly appreciated.
I'm pretty sure this is your problem:
float bouncer_dx = 8.0,bouncer_dy = -8.0;
^ notice it's always moving at 8px per game tick...
Further down in the code, you are checking if bouncer_x (and bouncer_y) is landing on a pixel that is exactly divisible by 8, and while it seems to work for the two original paddles, i'm willing to bet the bouncer_x value never equals the value to trigger this 'if' statement:
if(bouncer_x == left_sub_paddle_x+(paddle_width/1.0)) { ... }
because your new sub paddles have different width and math (divided by 1.0 and not 2.0)
Check it and see... this is just from looking over the code for a minute so i dunno for sure :)
Good luck!