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);
}
}
}
Related
I'm building Space Invaders in C++ (using the MBed platform) for a microcontroller. I've used a 2D Vector of object pointers to organise the invaders.
The movement algorithm is below, and runs in the main while loop for the game. Basically, I get the highest/lowest x and y values of invaders in the vector, and use those to set bounds based on screensize (the HEIGHT variable);
I also get the first invader's position, velocity, and width, which I apply changes to based on the bounds above.
Then I iterate through the whole vector again and apply all those changes. It sort of works – the invaders move – but the bounds don't seem to take effect, and so they fly off screen. I feel like I'm missing something really dumb, thanks in advance!
void Army::move_army() {
int maxy = HEIGHT - 20;
int Ymost = 0; // BOTTOM
int Yleast = 100; // TOP
int Xmost = 0; // LEFT
int Xleast = 100; // RIGHT
int first_row = _rows;
int first_column = _columns;
int firstWidth = 0;
Vector2D firstPos;
Vector2D firstVel;
for (int i = 0; i < _rows; i++) {
for (int n = 0; n < _columns; n++) {
bool state = invaders[i][n]->get_death();
if (!state) {
if (i < first_row && n < first_column) {
firstPos = invaders[i][n]->get_pos();
firstVel = invaders[i][n]->get_velocity();
firstWidth = invaders[i][n]->get_width();
}
Vector2D pos = invaders[i][n]->get_pos();
if (pos.y > Ymost) {Ymost = pos.y;} // BOTTOM
else if (pos.y < Yleast) {Yleast = pos.y;} // TOP
else if (pos.x > Xmost) {Xmost = pos.x;} // LEFT
else if (pos.x < Xleast) {Xleast = pos.x;} // RIGHT
}
}
}
firstVel.y = 0;
if (Xmost >= (WIDTH - 8) || Xleast <= 2) {
firstVel.x = -firstVel.x;
firstPos.y += _inc;
// reverse x velocity
// increment y position
}
else if (Ymost > maxy) {
_inc = -_inc;
// reverse increment
}
else if (Yleast < 2) {
_inc = -_inc;
// reverse increment
}
for (int i = 0; i < _rows; i++) {
int setx = firstPos.x;
if (i > 0) {firstPos.y += 9;}
for (int n = 0; n < _columns; n++) {
invaders[i][n]->set_velocity(firstVel);
invaders[i][n]->set_pos(setx,firstPos.y);
setx += firstWidth + 2;
}
}
It looks like you have your assignment cases reversed. Assignment always goes: right <- left, so in the first case you're changing the YMost value, not pos.y. It looks like if you swap those four assignments in your bounds checking it should work. Good luck!
I am trying to separate my collision detection into separate theads to improve the efficiency. The code I have now is:
/*CHECK COLLISION HERE*/
std::thread threads[6];
Vector2 birdPointsArr[6];
Vector2* birdPoints = getBirdPoints(birdPointsArr);
//check each pipe
for (int i = 0; i < 6; i++)
{
//only check pipes with viable x coords
if (pipes[i]->getX() < birdPoints[2].x + 20 && pipes[i]->getX() + pipes[i]->getW() > birdPoints[4].x - 20)
{
//check both upper and lower pipe
for (int j = 0; j < 2; j++)
{
Vector2 pipePointsArr[4];
Vector2* pipePoints = getPipePoints(pipePointsArr, i, j);
//only check pipes with viable y coords
if (j == 0 && birdPoints[0].y > pipePoints[2].y + 20)
{
continue;
}
if (j == 1 && birdPoints[3].y < pipePoints[0].y - 20)
{
continue;
}
threads[i] = std::thread([&]() {
//if x and y coords are viable, check collision
if (collisionDetection(birdPoints, pipePoints)) {
dead = true;
}
});
}
}
}
for (int i = 0; i < 6; i++)
{
if(threads[i].joinable())
threads[i].join();
}
My concern is that I am creating and destroying several threads each frame. I am concerned that all this creation and destruction makes my code slower than if I were to leave it synchronous; however, I don't know how to really measure that. Would it be faster if I just reverted it to serial form?
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
I'm making a neural network in c++ to traverse a maze knowing where the player is, which 2d direction it can move in (up,down,left,right) and where the goal is, i can at any time get the distance of the player to the goal as well
thus far this is my code
std::string NeuralNetwork::evolve(player p)
{
openMoves = p.getMoves();
playerPos = p.getListPos();
goalPos = p.getGoalPos();
values.clear();
for (auto item : openMoves)
values.push_back(item);
values.push_back(playerPos.x);
values.push_back(playerPos.y);
if (outputs.size() == 0)
outputs.resize(4);
if (inputs.size() == 0)
inputs.resize(values.size());
for (int i = 0; i < inputs.size(); i++)
{
inputs[i].srcValue = values[i];
if (inputs[i].weightList.size() == 0)
{
for (int j = 0; j < outputs.size(); j++)
{
inputs[i].weightList.push_back(dist(100) / 100.0f);
}
}
}
for (int i = 0; i < outputs.size(); i++)
{
outputs[i].out = 0;
if (outputs[i].theta == NULL)
outputs[i].theta = dist(-100, 100) / 100.0f;//rand funct to produce int between -100-100 then divide by 100 to get theta between -1 and 1
for (auto a : inputs)
{
outputs[i].out += (a.srcValue * a.weightList[i]);
}
outputs[i].finalOut = outputs[i].out / (1.0f + fabs(outputs[i].out));
//outputs[i].finalOut = 1 / (1 + std::pow(exp(1), -(outputs[i].out - outputs[i].theta)));
}
for (int i = 0; i < outputs.size(); i++)//backwards prop
{
float e = 1 - outputs[i].finalOut;
float delta = outputs[i].finalOut * (1 - outputs[i].finalOut)*e;
for (int j = 0; j < inputs.size(); j++)
{
inputs[j].weightList[i] += alpha * inputs[j].srcValue * delta;
}
outputs[i].theta += alpha * (-1)*delta;
}
the neural network is a function that's called every frame, the player starts in the top left and the goal is in the bottom right, the function returns a direction for the player to move in.
however, using backwards propagation each output final is never 1 which is what I use to determine its direction using
for (int i = 0; i < outputs.size(); i++)
{
if (outputs[0].finalOut == 1)//left
{
return "01";
}
else if (outputs[1].finalOut == 1)//up
{
return "10";
}
else if (outputs[2].finalOut == 1)//down
{
return "11";
}
else if (outputs[3].finalOut == 1)//right
{
return "00";
}
}
return "";}
however the function always returns no movement at all and i'm not sure why, even after a few minutes of waiting, there are no hidden layers to the network i'm starting simple with the inputs directly linking to the output
i'm unsure if my error calculation is correct to then adjust the weights. i'm unsure what i should be using to allow the ai to determine how to move
So I'm relatively new to coding in SFML, so apologies if I made some newbie mistake. My project is Space Invaders in SFML. When I was working on the shooting, a problem arose. How do I do collision? I was familiar with shape.getGlobalBounds().intersect(), and it worked on previous projects. It didn't work. So I tried simplifying it. I used RectangleShape for both the enemy shape, and the bullet shape.
Here is the actual for loop, for the collision:
for (int y = 0; y <= 2; ++y) {
for (int x = 0; x <= 6; ++x) {
if (shootShape.getPosition().x < e.aliensX[x] && shootShape.getPosition().x > e.aliensX[x] + 15 ||
shootShape.getPosition().y < e.aliensY[y] && shootShape.getPosition().y > e.aliensY[y] + 15) {
e.aliensX[x] = -10;
e.aliensY[y] = -10;
shooting = false;
reload = false;
}
}
}
This is the shooting function:
void Player::shoot() {
if (reload) {
shootX = posX + 5;
shootY = posY - 50;
shootShape.setPosition(shootX, shootY);
shooting = true;
reload = false;
}
if (shooting) {
shootY -= 150 * 2 * deltaTime;
shootShape.setPosition(shootX, shootY);
}
}
And this is how I draw the enemies (I don't know how to create multiple enemies):
void Enemy::drawAliens() {
for (int j = 0; j <= arraySizeY; ++j) {
for (int i = 0; i <= arraySizeX; ++i) {
actualShape.setPosition(aliensX[i], aliensY[j]);
if (aliensY[i] <= p.shootY && aliensY[i] >= p.shootY) {
aliensX[i] = -10;
aliensY[i] = -10;
}
else {
win.draw(actualShape);
}
}
}
}
Explanation behind some of the variables:
aliensX is an array which contains the different x positions for the enemies.
aliensY is an array which contains the different y positions for the enemies.
shooting is a bool variable, which is true when the bullet is travelling.
reload is whether you can shoot.
EDIT:
Intersect will not work because of the way I created my enemies. They are all in ONE shape. I need it to work with specific coordinates, because I don't know a better way to create multiple enemies all at once. If there is a way to do that, advice would be appreciated!
It's rather easy, if you rely on SFML's templated sf::Rect class. Just retrieve the rectangle for both objects as global boundaries and try to intersect them:
const bool collides = firstDrawable.getGlobalBounds().intersect(secondDrawable.getGlobalBounds());`
Same can be done with a small temporary rectangle you can fill with dynamic values not directly associated with a sf::Drawable:
const sf::FloatRect bullet(x - width / 2, y - height / 2, width, height);
const bool collides = firstDrawable.getGlobalBounds().intersect(bullet);`
Your if statement is never true. You have
shootShape.getPosition().x < e.aliensX[x] && shootShape.getPosition().x > e.aliensX[x] + 15.
Your shootShape.getPosition().x can never be smaller than e.aliensX[x] and bigger than e.aliensX[x] + 15 at the same time. That's impossible. The same for y position. Change your if statement to
for (int y = 0; y <= 2; ++y) {
for (int x = 0; x <= 6; ++x) {
if (shootShape.getPosition().x > e.aliensX[x] && shootShape.getPosition().x < e.aliensX[x] + 15 ||
shootShape.getPosition().y > e.aliensY[y] && shootShape.getPosition().y < e.aliensY[y] + 15) {
e.aliensX[x] = -10;
e.aliensY[y] = -10;
shooting = false;
reload = false;
}
}
}