MyPawn.cpp
// Called every frame
void AMyPawn::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
// Handle growing and shrinking based on our "Grow" action
{
float CurrentScale = OurVisibleComponent->GetComponentScale().X;
if (bGrowing)
{
// Grow to double size over the course of one second
CurrentScale = CurrentScale + 2;
}
else
{
// Shrink half as fast as we grow
CurrentScale -= (DeltaTime * 0.5f);
}
// Make sure we never drop below our starting size, or increase past double size.
CurrentScale = FMath::Clamp(CurrentScale, 1.0f, 2.0f);
OurVisibleComponent->SetWorldScale3D(FVector(CurrentScale));
}
// Handle movement based on our "MoveX" and "MoveY" axes
{
if (!CurrentVelocity.IsZero())
{
FVector NewLocation = GetActorLocation() + (CurrentVelocity * DeltaTime);
SetActorLocation(NewLocation);
}
}
}
MyPawn.h
#include "GameFramework/Pawn.h"
#include "MyPawn.generated.h"
UCLASS()
class MYPROJECT_API AMyPawn : public APawn
{
GENERATED_BODY()
public:
// Sets default values for this pawn's properties
AMyPawn();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
// Called to bind functionality to input
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
UPROPERTY(EditAnywhere)
USceneComponent* OurVisibleComponent;
//Input functions
void Move_XAxis(float AxisValue);
void Move_YAxis(float AxisValue);
void StartGrowing();
void StopGrowing();
//Input variables
FVector CurrentVelocity;
bool bGrowing;
};
I want to add a statement that make my Spawn move faster every Frame or Second while one of the key input pressed (Forward,Backward,Left or Right),
I've tried to add
CurrentVelocity.X += CurrentVelocity.X
or
CurrentVelocity.X += 1
in the AMyPawn::Tick, and tried some more combination with no success, hope u can help me solve this .
Related
I am facing an issue while generating a random point in a volume using KismetLibrary,
there is the code
#include "Spawner.h"
#include "Components/BoxComponent.h"
#include "Kismet/KismetMathLibrary.h"
#include "BaseCell.h"
// Sets default values
ASpawner::ASpawner()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
SpawningVolume = CreateDefaultSubobject<UBoxComponent>(TEXT("SpawnVolumeBox"));
RootComponent = SpawningVolume;
Cell = ABaseCell::StaticClass();
}
// Called when the game starts or when spawned
void ASpawner::BeginPlay()
{
Super::BeginPlay();
SpawnCells();
}
// Called every frame
void ASpawner::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
void ASpawner::SpawnCells()
{
if(Cell != NULL)
{
UWorld* const World = GetWorld();
if (World) {
FVector Origin = SpawningVolume->Bounds.Origin;
FVector Extent = SpawningVolume->Bounds.BoxExtent;
FVector SpawnLocation = UKismetMathLibrary::RandomPointInBoundingBox(Origin, Extent);
FRotator SpawnRotation;
SpawnRotation.Pitch = FMath::FRand() * 360.0f;
SpawnRotation.Roll = FMath::FRand() * 360.0f;
SpawnRotation.Yaw = FMath::FRand() * 360.0f;
ABaseCell* SpawnedCell = World->SpawnActor<ABaseCell>(Cell, SpawnLocation, SpawnRotation);
}
}
}
I should be able to generate without using Kismet the random point but i thought if this kind of library exists we should use them...
it's throwing the following error: https://i.stack.imgur.com/6nG45.png
EDIT
when trying to debug i figured that actually it's when i'm accessing private property "SpawningVolume" that error is thrown... still can't figure why
here is the Spawner.h
#include "BaseCell.h"
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Spawner.generated.h"
UCLASS()
class LIFE_API ASpawner : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
ASpawner();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
// Spawnable
UPROPERTY(EditAnyWhere, category="Spawning")
TSubclassOf<class ABaseCell> Cell;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
private:
// SpawningVolume as BoxComponent
UPROPERTY(VisibleAnyWhere, category="Spawning", meta=(AllowPrivateAccess="true"))
class UBoxComponent* SpawningVolume;
void SpawnCells();
};
EDIT 2
Just added this condition and it seems that "SpawningVolume" is "nullptr" so i don't know what i'm doing wrong but i keep investigating
void ASpawner::SpawnCells()
{
if(Cell != NULL)
{
UWorld* const World = GetWorld();
if (World) {
// Added condition
if (SpawningVolume != nullptr) {
FVector Origin = SpawningVolume->Bounds.Origin;
FVector Extent = SpawningVolume->Bounds.BoxExtent;
FVector SpawnLocation = UKismetMathLibrary::RandomPointInBoundingBox(Origin, Extent);
FRotator SpawnRotation;
SpawnRotation.Pitch = FMath::FRand() * 360.0f;
SpawnRotation.Roll = FMath::FRand() * 360.0f;
SpawnRotation.Yaw = FMath::FRand() * 360.0f;
ABaseCell* SpawnedCell = World->SpawnActor<ABaseCell>(Cell, SpawnLocation, SpawnRotation);
}
}
}
}
ERROR
Unhandled Exception: EXCEPTION_ACCESS_VIOLATION reading address 0x000000000000012c
UE4Editor_Life_0001!ASpawner::SpawnCells() [C:\Users\Benja\OneDrive\Documents\Unreal Projects\Life\Source\Life\Spawner.cpp:46]
So I've had a lot of trouble with Cocos2d's auto-release shenanigans, and (almost) wish that I could just handle all of that myself...
Anyways, the problem I've had is with creating some animations. I've got a class called AnimatedDamageableSprite which inherits from DamageableSprite which inherits from Sprite which inherits from CCSprite etc...
When I create an AnimatedDamageableSprite, I have a successful animation on the screen, which runs as it should.
When I create a Suicider, which (you guessed it) inherits from AnimatedDamageableSprite, the CCArray which contains the frames for animation doesn't survive beyond the first loop, and on the second update attempt, the program gets an AV error.
Here's the code for the two classes:
Sprite.h
// This class works
class AnimatedDamageableSprite :public DamageableSprite {
public:
AnimatedDamageableSprite(int hp, CCPoint pos, CCTexture2D* tex, int rows, int columns, float scaleX, float scaleY);
virtual ~AnimatedDamageableSprite();
virtual void update(float dt);
virtual bool updateFrame(float dt);
virtual SpriteType getType() { return ANIMATED_DAMAGEABLE_SPRITE; };
protected:
float m_frameNum;
CCArray* m_frames;
int m_numOfFrames;
};
// This class doesn't
class Suicider :public AnimatedDamageableSprite {
public:
Suicider(int difficulty);
virtual ~Suicider();
virtual void update(float dt);
virtual SpriteType getType() { return SUICIDER; };
private:
float m_speed;
};
Sprite.cpp
AnimatedDamageableSprite::AnimatedDamageableSprite(int hp, CCPoint pos, CCTexture2D* tex, int rows, int columns, float scaleX, float scaleY)
:DamageableSprite(hp, pos, tex, scaleX, scaleY), m_frameNum(0), m_numOfFrames(rows*columns) {
float texWidth = tex->getContentSize().width / (float)columns;
float texHeight = tex->getContentSize().height / (float)rows;
m_frames = CCArray::createWithCapacity(m_numOfFrames);
m_frames->retain();
for (unsigned int i = 0; i < columns; i++) {
for (unsigned int j = 0; j < rows; j++) {
CCRect r(i*texWidth, j*texHeight, texWidth, texHeight);
m_frames->addObject(new CCSpriteFrame);
((CCSpriteFrame*)m_frames->lastObject())->createWithTexture(tex, r);
((CCSpriteFrame*)m_frames->lastObject())->initWithTexture(tex, r);
m_frames->lastObject()->retain();
}
}
initWithSpriteFrame((CCSpriteFrame*)m_frames->objectAtIndex(m_frameNum));
setTexture(tex);
setPosition(pos);
setScaleX(scaleX);
setScaleY(scaleY);
updateTransform();
}
// This function is called every frame. It returns a boolean for unrelated reasons
bool AnimatedDamageableSprite::updateFrame(float dt) {
bool retVal = false;
// Assume animations are at 30 FPS for now
m_frameNum += dt * 0.03f;
while (m_frameNum >= m_numOfFrames) {
m_frameNum -= m_numOfFrames;
retVal = true;
}
setDisplayFrame((CCSpriteFrame*)m_frames->objectAtIndex(m_frameNum));
updateTransform();
return retVal;
}
// This class calls the constructor of the one that works, and does nothing else relevant to the problem
// It also doesn't override the updateImage() function
Suicider::Suicider(int difficulty)
: AnimatedDamageableSprite(1, CCPoint(10,10), g_textureManager.getTexture("Suicider Sheet"), 6, 10, SCALE_WIDTH, SCALE_HEIGHT) {
// ...
}
EDIT:
Seems I forgot to actually point out the problem.
The CCArray* m_frames declared in AnimatedDamageableSprite is fine when used in that instance, but it is deleted at the end of a frame when used in the Suicider class - i.e. it isn't being retained. Hence the AV error when I try to access an item inside it which no-longer exists
I tried retaining it in the Suicider constructor as well, although that didn't change anything.
I'm trying to make a simple game, basically there is a map that you can put walls on, after that the enemy will spawn and walk to the finish tile.
Here's the call stack
Game constructor (setscene etc, create buildwall object that handles the wall placement) -> BuildWall (inputs are handled by this object, after user pressed Enter, call the game.generatePath) -> game.generatePath(here's where some of the member variables are not accessible)
Here is the code:
Game.h
#ifndef GAME
#define GAME
#include "Wall.h"
#include "Tile.h"
#include "Enemy.h"
#include "Path.h"
#include <QGraphicsView>
#include "Tower.h"
class BuildWall;
class Game: public QGraphicsView{
Q_OBJECT
public:
Game();
QGraphicsScene * scene;
Wall * build_wall;
// map and tile details
int map_width_in_tiles; // number of tiles in x axis
int map_height_in_tiles;
int map_tile_size; // in pixels
// tiles are indexed in int for easy sorting in QMap. We must use indexOfPoint(x,y) to get an index of a tile
QMap<int,Tile*> tiles;
// spawning entities
void spawnBlueSlime(Tile &spawn, Tile &dest, Path &path);
int getTileSize();
QMap<int,Tile*> getTiles();
void generatePath();
// tile indexing
int indexOfPoint(int x, int y);
// convert tile coordinate to scene coordinate
int x_scene(int x);
int y_scene(int y);
Tower *tower;
void mouseMoveEvent(QMouseEvent *event);
private:
// game initializations
void createMapTiles(QString filename);
void createScene();
void setMapTile(int map_width_in_tiles, int map_height_in_tiles, int map_tile_size_);
// debugging
void drawTilesOverlay(QString filename);
void drawTilesPoint();
//
void printAllTiles();
// mouse input
// spawn dest
Tile *spawn1;
Tile *dest1;
Tile *spawn2;
Tile *dest2;
BuildWall *buildwall;
};
#endif // GAME
Game.cpp
Game::Game()
{
setMouseTracking(true);
grabMouse();
setMapTile(20,10,64); // but start from 0
createScene();
createMapTiles(":/floor/assets/floor/dirt.png");
//drawTilesOverlay(":/util/assets/util/sTrackBorder_0.png");
//drawTilesPoint();
//printAllTiles();
int index = indexOfPoint(19,4);
Tower *tower = new Tower(*this,this->tiles.value(index)->x(),this->tiles.value(index)->y());
BuildWall *buildwall = new BuildWall(*this);
}
void Game::generatePath() {
delete buildwall;
Tile *spawn1 = tiles.value(indexOfPoint(1,5));
Tile *dest1 = tiles.value(indexOfPoint(19,5));
Path *path = new Path(*this,*spawn1,*dest1);
spawnBlueSlime(*spawn1,*dest1, *path);
}
//
// others methods
BuildWall.h
class Game;
class BuildWall: public QGraphicsPixmapItem{
public:
BuildWall(Game &game_);
Game &game;
private:
void keyPressEvent(QKeyEvent *ev);
};
BuildWall.cpp
BuildWall::BuildWall(Game &game_) : game(game_)
{
setPixmap(QPixmap(":/wall/assets/wall/brick_red.png"));
setScale(0.5);
game.scene->addItem(this);
this->setFlag(QGraphicsItem::ItemIsFocusable, true);
this->setFocus();
}
void BuildWall::keyPressEvent(QKeyEvent *ev)
{
int grid = game.map_tile_size;
switch (ev->key())
{
//other keys
case Qt::Key_Return:
this->setFlag(QGraphicsItem::ItemIsFocusable, false);
this->setFocus();
game.generatePath();
break;
}
}
Here you can see I can access some of the member variables such as tiles which are generated in Game constructor
You are shadowing member variables.
In the constructor it should only say:
buildwall = new BuildWall(*this);
This is the case for all member variables (spawn1, dest1, spawn2, dest2, buildwall) and in all functions where you want to call these variables.
In my gaming context, the sprite is a smiling baby, when the baby is touched, the current sprite image changed to a crying baby, then after 3 seconds of crying sound effect ended, the sprite will restore to the smiling baby image.
My problem is
How to swap back with the previous image?
I have changed the smiling baby to a crying one, but i have no idea how could I swap it with the original smiling one?
How to ensure one click at one time?
Each time the baby sprite is touched, the audio will start to play which is not ideal, because I hope the event function is only called after the previous event process is finished.
here is my code, and thank you a lot!
bool HelloWorld::init()
{
// 1. super init first
if ( !Layer::init() )
{
return false;
}
Size visibleSize = Director::getInstance()->getVisibleSize();
Vec2 origin = Director::getInstance()->getVisibleOrigin();
//add background scene
auto backgroundSprite = Sprite :: create("scene001.jpg");
backgroundSprite->setAnchorPoint(Vec2(0,0));
backgroundSprite->setScaleX((visibleSize.width / backgroundSprite->getContentSize().width) * 1);
backgroundSprite->setScaleY((visibleSize.height / backgroundSprite->getContentSize().height) * 1);
addChild(backgroundSprite);
//add smileBaby sprite
auto smileBabySprite = Sprite :: create("figure001.png");
smileBabySprite -> setPosition(Vec2(500,400));
addChild(smileBabySprite);
//add crying audio
auto audio = CocosDenshion::SimpleAudioEngine::getInstance();
auto babyListener = EventListenerTouchOneByOne::create();
babyListener -> onTouchBegan = [smileBabySprite, audio](Touch* touch, Event* event)
{
//change smileBaby sprite to cryingBaby sprite
smileBabySprite->setTexture(CCTextureCache::sharedTextureCache()->addImage("figure002.png"));
audio -> playEffect("babycry.mp3",false,1.0f,1.0f,1.0f);
return true;
};
babyListener -> onTouchEnded=[smileBabySprite](Touch* touch, Event* event )
{
};
_eventDispatcher -> addEventListenerWithSceneGraphPriority(babyListener, this);
return true;
}
What you want is to keep state about if the baby is crying or not. The best thing to do is keep this logic in a custom Node subclass.
Here is some (almost pseudo-)code to get you started:
Baby.h:
#pragma once
#include "cocos2d.h"
class Baby : public cocos2d::Node
{
private:
cocos2d::Sprite *_sprite; // Weak reference
bool _crying;
float _cryingTime;
public:
CREATE_FUNC(Baby);
protected:
virtual bool init() override;
virtual void update(float delta) override;
public:
void touched();
bool isInside(cocos2d::Touch *touch) const
protected:
void setSprite();
};
Baby.cpp:
#include "Baby.h"
USING_NS_CC;
bool Baby::init()
{
if (!Node::init())
return false;
_crying = false;
setSprite();
scheduleUpdate();
return true;
}
void Baby::update(float delta)
{
Node::update(delta);
if (_crying) {
_cryingTime -= delta;
if (_cryingTime <= 0.0f) {
_crying = false;
setSprite();
}
}
}
void Baby::touched()
{
if (_crying)
return; // Already crying
_crying = true;
_cryingTime = 3.0f; // Length of audio, I guess?
setSprite();
// Start crying sound here
}
bool Baby::isInside(Touch *touch) const
{
Vec2 locationInNode = _sprite->convertToNodeSpace(touch->getLocation());
Size size = _sprite->getContentSize();
Rect rect = Rect(0.0f, 0.0f, size.width, size.height);
return rect.containsPoint(locationInNode);
}
void Baby::setSprite()
{
if (_sprite)
_sprite->removeFromParent();
_sprite = Sprite::initWithFile(_crying ? "baby_crying.png" : "baby.png");
Vec2 size = getContentSize();
_sprite->setPosition(size.width * 0.5f, size.height * 0.5f);
addChild(_sprite);
}
You add the Baby node in the parent instead of the sprite, using:
_baby = Baby::create();
_baby->setPosition(Wherever);
addChild(_baby);
Where _baby is an instance variable and use the isInside() method to test if a touch event is within the bounds of the sprite and call its touched() method:
Touch *touch = ...;
if (_baby->isInside(touch)) {
_baby->touched();
}
and the Baby object will ignore the touch depending on state.
I am currently stuck trying to create a grid for my controllable snake to move around. Currently. I am using a resolution of 1024x768 and would like the snake to move between a 16x16 grid (64x48 resolution)
So far the snake just moves pixel by pixel at a set speed.
I'll paste the .cpp and .hpp files below which i think are relevant to where i need to implement the code. If anyone could provide any suggestions/code that would be great!
snake.cpp
#include "snake.hpp"
#include <cstdlib>
void Snake::move()
{
switch(direction_){
case Direction::North:
position_.y += 1;
break;
case Direction::East:
position_.x += 1;
break;
case Direction::South:
position_.y -= 1;
break;
case Direction::West:
position_.x -= 1;
}
if (position_.x < 0) position_.x = 63; else if (position_.x > 63) position_.x = 0;
if (position_.y < 0) position_.y = 47; else if (position_.y > 47) position_.y = 0;
}
void Snake::render(prg::Canvas& canvas) const
{
canvas.drawCircle(getPosition().x * 16, getPosition().y * 16,16,prg::Colour::WHITE);
}
void Snake::changeDirection(Direction new_direction)
{
direction_ = new_direction;
}
snake.hpp
#if !defined SNAKE_HPP
#define SNAKE_HPP
#include <prg_interactive.hpp>
enum class Direction {
North = 1, East, South, West
};
struct Position final {
int x{0}, y{0};
Position(int ix, int iy) : x{ix}, y{iy} {}
};
class Snake {
public:
virtual ~Snake() {}
virtual void move();
void render(prg::Canvas& canvas) const;
void changeDirection(Direction new_direction);
const Position& getPosition() const {return position_;}
void setPosition(const Position& position){ position_ = position;}
private:
Direction direction_ {Direction::North};
Position position_ {0,0};
};
class PlayerSnake : public Snake,
public prg::IKeyEvent {
public:
PlayerSnake();
virtual ~PlayerSnake();
bool onKey(const prg::IKeyEvent::KeyEvent& key_event) override;
};
#endif // SNAKE_HPP
play_state.cpp
#include "play_state.hpp"
#include "ai_snake.hpp"
#include "player_snake.hpp"
#include <iostream>
const size_t MaxShapes {5};
const unsigned int MaxScale {5};
bool PlayState::onCreate()
{
snakes_.push_back(new AISnake);
snakes_.back()->setPosition(Position(100,100));
snakes_.push_back(new PlayerSnake);
snakes_.back()->setPosition(Position(50,50));
double x, y;
for(unsigned shape = 0;shape < MaxShapes;shape++)
{
x = (double)(rand() % prg::application.getScreenWidth());
y = (double)(rand() % prg::application.getScreenHeight());
shapes_.push_back(Square({x, y}));
}
return true;
}
bool PlayState::onDestroy()
{
return true;
}
void PlayState::onEntry()
{
prg::application.addKeyListener(*this);
game_timer_.start();
}
void PlayState::onExit()
{
prg::application.removeKeyListener(*this);
game_timer_.stop();
}
void PlayState::onUpdate()
{
}
void PlayState::onRender(prg::Canvas& canvas)
{
const std::string text = "";
canvas.blitFast(
background_,
canvas.getWidth() / 2 - background_.getWidth() / 2,
canvas.getHeight() / 2 - background_.getHeight() / 2
);
prg::uint text_dims[2];
prg::Font::MASSIVE.computePrintDimensions(text_dims, text);
prg::Font::MASSIVE.print(
canvas,
prg::application.getScreenWidth() / 2 - text_dims[0] / 2,
prg::application.getScreenHeight() / 2 - text_dims[1] / 2,
prg::Colour::RED,
text);
for(const auto snake : snakes_) {
snake->render(canvas);
}
for(Shape shapes : shapes_) {
shapes.render(canvas);
}
}
bool PlayState::onKey(const prg::IKeyEvent::KeyEvent& key_event)
{
if(key_event.key_state == KeyEvent::KB_DOWN) {
switch(key_event.key) {
case KeyEvent::KB_ESC_KEY:
prg::application.exit();
break;
}
}
return true;
}
void PlayState::onTimer(prg::Timer& timer)
{
for(auto snake : snakes_) {
snake->move();
}
}
play_state.hpp
#if !defined PLAY_STATE_HPP
#define PLAY_STATE_HPP
#include <prg_interactive.hpp>
#include "snake.hpp"
#include "square.hpp"
#include <list>
//Example of forward declaration of Snake class
class Snake;
class PlayState final : public prg::IAppState,
public prg::IKeyEvent,
public prg::ITimerEvent {
public:
PlayState() = default;
bool onCreate() override;
bool onDestroy() override;
void onEntry() override;
void onExit() override;
void onUpdate() override;
void onRender(prg::Canvas& canvas) override;
bool onKey(const prg::IKeyEvent::KeyEvent& key_event) override;
void onTimer(prg::Timer& timer) override;
private:
//Snake* snakes_[2] {nullptr,nullptr};
std::list<Snake*> snakes_;
prg::Timer game_timer_ {0, 1000 / 30, *this};
const prg::Image background_ {prg::ImageFile("resources/images/border.bmp").load()};
std::vector<Shape> shapes_;
};
#endif // PLAY_STATE_HPP
player_snake.cpp
#include "player_snake.hpp"
//PlayerSnake Implementation
//
PlayerSnake::PlayerSnake()
{
prg::application.addKeyListener(*this);
}
PlayerSnake::~PlayerSnake()
{
prg::application.removeKeyListener(*this);
}
bool PlayerSnake::onKey(const prg::IKeyEvent::KeyEvent& key_event)
{
if(key_event.key_state == KeyEvent::KB_DOWN) {
switch(key_event.key) {
case KeyEvent::KB_LEFT_KEY:
changeDirection(Direction::West);
break;
case KeyEvent::KB_RIGHT_KEY:
changeDirection(Direction::East);
break;
case KeyEvent::KB_UP_KEY:
changeDirection(Direction::North);
break;
case KeyEvent::KB_DOWN_KEY:
changeDirection(Direction::South);
break;
}
}
return true;
}
player_snake.hpp
#if !defined PLAYER_SNAKE_HPP
#define PLAYER_SNAKE_HPP
#include "snake.hpp"
#include <prg_interactive.hpp>
#endif //PLAYER_SNAKE_HPP
You snake is initially set out of bounds:
snakes_.push_back(new AISnake);
snakes_.back()->setPosition(Position(100,100));
snakes_.push_back(new PlayerSnake);
snakes_.back()->setPosition(Position(50,50));
Because in the move function, you limit the snake to (64, 48) as the maximum location. The x position 100 is past the limit. The y positions are past the limit.
You may want to set them at different locations based on the MAXIMUM_WIDTH and MAXIMUM_HEIGHT constants (see my comments):
Snake AISnake;
AISnake.setPosition(MAXIMUM_WIDTH / 4, MAXIMUM_HEIGHT / 4);
snakes_.push_back(AISnake);
Snake PlayerSnake;
PlayerSnake.setPosition(MAXIMUM_WIDTH * 3 / 4,
MAXIMUM_HEIGHT * 3 / 4);
snakes_.push_back(PlayerSnake);
Also note that in the above code fragment, there is no dynamic memory allocation. The variables (snakes) are defined locally and copied into the snakes_ container. This means that there is no need to worry about memory leaks or memory management (like when to delete the memory occupied by the snake).
More Out Of Bounds
Some places, you use the screen dimensions for the boundaries, others, you use a hard coded value:
x = (double)(rand() % prg::application.getScreenWidth());
y = (double)(rand() % prg::application.getScreenHeight());
You need to decide whether the game board occupies the entire screen dimensions or is a fixed size. If you keep the above statements, you should test the positions to verify they are within the game borders.
If this is a GUI application, you need to decide on a fixed size game board or a board set to the size of the window or expanding to the entire screen. For a fixed size board, you should consider a "viewport" design. This means that the window is a view or port showing a small portion of the board (the board is bigger than the window).
Separation of Screen Vs. Board
You should separate the concepts between a logical board and the physical screen. This concept lets you adapt the board to the screen without affecting any other modules.
For example, the Board draws onto the screen. A Board cell may have different pixel dimensions depending on the screen resolution. However, a part of the snake will always occupy at least one Board cell. So the snake movement doesn't depend on the screen resolution, only the Board dimensions.
By placing the objects, Board and Screen, in separate files, you can change the screen dimensions without having to recompile any of the snake or main files.