RPG style sprite movement with SDL2 using Crystal - sdl-2

I'm using SDL2 with Crystal to make a 16bit RPG style tile-based game. I've seen this question asked a ton, but even with all the answers I've come across, I'm still not getting the movement I'm looking for. Have you ever played Final Fantasy IV, V, or VI on the SNES? I'm looking for movement like that. No diagonal, character is always over a tile, and never stops between 2 tiles.
# main game loop
loop do
ticks = Time.monotonic.milliseconds / 1000.0
case event = SDL::Event.poll
when SDL::Event::Keyboard
case event.sym
when .right?
character.move_right(ticks)
end
end
character.draw(renderer)
renderer.present
#other code handling break and stuff omitted
end
# character.cr
VELOCITY = 100
def move_right(delta_ticks)
#direction_facing = "east"
#x += VELOCITY * delta_ticks
end
def draw(renderer)
sprite = #directions[#direction_facing]
renderer.copy(sprite, dstrect: SDL::Rect[#x.to_i, #y.to_i, 64, 64])
end
The way my current movement works, the character starts walking slow, then picks up speed then drops back down to walking slow like it's shifting gears or something. I know my line #x += VELOCITY * delta_ticks is wrong, but I wasn't able to find one that worked how I wanted. This also doesn't take in to account stopping directly over a tile (in this case 64x64).
EDIT: I've tried to transpose the suggestion #genpfault gave. It still doesn't do what I want, but since I don't know C++, I may have missed some stuff. That code update is here

Make a little "tasklet" helper (I know zero about Crystal; in C++ I'd just have this be a class/struct with member data & functions) that encapsulates the character's current tile x/y position (and fine, sub-tile x/y position)
When you handle the left/right/up/down input, check if a current tasklet is still doing its thing; if not, make a new tasklet with the desired direction
Each frame while a tasklet is active, process it: increment/decrement (1px/frame? up to you) the character's fine x/y position until it hits the goal tile position; if the tasklet hits the goal position this frame, remove it (and update the character's tile position)
This way you prevent new input from interfering with character motion while it's in progress, as well as smoothly animating tile transitions.
Something like this:
#include <SDL2/SDL.h>
#include <memory>
struct Character
{
int m_TileX;
int m_TileY;
int m_FineX; // in 16ths of a tile
int m_FineY; // in 16ths of a tile
};
class ITask
{
public:
virtual ~ITask() {};
// override & return true to indicate this task is done
virtual bool Run() = 0;
};
class CharacterAnimator : public ITask
{
public:
CharacterAnimator( Character& c, int dx, int dy )
: m_C( c )
, m_Dx( dx )
, m_Dy( dy )
{}
~CharacterAnimator() override {}
bool Run() override
{
m_C.m_FineX += m_Dx;
m_C.m_FineY += m_Dy;
bool done = false;
if( m_C.m_FineX <= -16 ) { m_C.m_TileX--; m_C.m_FineX = 0; done = true; }
if( m_C.m_FineY <= -16 ) { m_C.m_TileY--; m_C.m_FineY = 0; done = true; }
if( m_C.m_FineX >= 16 ) { m_C.m_TileX++; m_C.m_FineX = 0; done = true; }
if( m_C.m_FineY >= 16 ) { m_C.m_TileY++; m_C.m_FineY = 0; done = true; }
return done;
}
private:
Character& m_C;
int m_Dx;
int m_Dy;
};
int main( int argc, char** argv )
{
SDL_Init( SDL_INIT_EVERYTHING );
SDL_Window * window = SDL_CreateWindow
(
"SDL2",
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
640, 480,
SDL_WINDOW_SHOWN
);
SDL_Renderer* renderer = SDL_CreateRenderer
(
window,
0,
SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC
);
SDL_RenderSetLogicalSize( renderer, 320, 240 );
Character c;
c.m_TileX = 9;
c.m_TileY = 7;
c.m_FineX = 0;
c.m_FineY = 0;
std::unique_ptr< ITask > movementTask;
bool running = true;
while( running )
{
if( movementTask && movementTask->Run() )
{
movementTask.reset();
}
SDL_Event ev;
while( SDL_PollEvent( &ev ) )
{
if ( ev.type == SDL_QUIT )
running = false;
if( ev.type == SDL_KEYUP && ev.key.keysym.sym == SDLK_ESCAPE )
running = false;
if( ev.type == SDL_KEYDOWN && ev.key.keysym.sym == SDLK_UP && !movementTask )
movementTask = std::unique_ptr< ITask >( new CharacterAnimator( c, 0, -1 ) );
if( ev.type == SDL_KEYDOWN && ev.key.keysym.sym == SDLK_DOWN && !movementTask )
movementTask = std::unique_ptr< ITask >( new CharacterAnimator( c, 0, 1 ) );
if( ev.type == SDL_KEYDOWN && ev.key.keysym.sym == SDLK_LEFT && !movementTask )
movementTask = std::unique_ptr< ITask >( new CharacterAnimator( c, -1, 0 ) );
if( ev.type == SDL_KEYDOWN && ev.key.keysym.sym == SDLK_RIGHT && !movementTask )
movementTask = std::unique_ptr< ITask >( new CharacterAnimator( c, 1, 0 ) );
}
SDL_SetRenderDrawColor( renderer, 0, 0, 0, 255 );
SDL_RenderClear( renderer );
// draw character
SDL_SetRenderDrawColor( renderer, 255, 0, 0, 255 );
SDL_Rect r =
{
c.m_TileX * 16 + c.m_FineX,
c.m_TileY * 16 + c.m_FineY,
16,
16
};
SDL_RenderFillRect( renderer, &r );
SDL_RenderPresent( renderer );
}
SDL_DestroyRenderer( renderer );
SDL_DestroyWindow( window );
SDL_Quit();
return 0;
}

Related

GLSL math conditional AND

Maybe I'm not understanding the language or maybe the compiler is doing some kind of black magic but this code is not identical if I uncomment the comment which surprises me because to accept the conditional that should be the value of the variable :
`
while (distance < tMax) {
coords = uvec3(-1, -1, -1);
int active_voxel = volume_data_box_get_coords_from_point(
mi.block, first_prim_offset, mi.min.xyz, mi.max.xyz,
mi.slices_by_dimension, mi.memory_size, mi.voxel_size, hit, coords);
if ((active_voxel == 1) && (coords.x == 0) && (coords.y == 0) &&
(coords.z == 0)) {
// coords.x = 0;
// coords.y = 0;
// coords.z = 0;
bool are_extents = volume_data_box_get_extents_from_coords(
mi.block, first_prim_offset, mi.min.xyz, mi.slices_by_dimension, mi.memory_size,
mi.voxel_size, coords, voxel_extents);
if (are_extents) {
s = intersectRayOBB(ray.origin, ray.direction, mi.transform,
voxel_extents.min, voxel_extents.max);
tHit = s.t;
voxel_uv = s.uv;
hitKind = 1;
break;
}
}
// Update hit point from previous point plus direction multiplied by
// voxel size
hit += ray.direction * mi.voxel_size;
// Calculate distance between new hit point and ray origin
distance = length(hit - ray.origin);
}
`
I hope someone can clarify what is going on. Thanks!
The evaluated value is different from the expected one.

How to add settings to snake game(Processing)?

Im trying to add settings to a snake game made in processing. I want to have something like easy, normal and hard or something along the lines of that and change the speed and maybe size of the grid. If anyone coudl explain how to id greatly appreciate it!
ArrayList<Integer> x = new ArrayList<Integer>(), y = new ArrayList<Integer>();
int w = 30, h = 30, bs = 20, dir = 2, applex = 12, appley = 10;
int[] dx = {0,0,1,-1}, dy = {1,-1,0,0};
boolean gameover = false;
void setup() {
size(600,600);
x.add(5);
y.add(5);
}
void draw() {
background(255);
for(int i = 0 ; i < w; i++) line(i*bs, 0, i*bs, height); //Vertical line for grid
for(int i = 0 ; i < h; i++) line(0, i*bs, width, i*bs); //Horizontal line for grid
for(int i = 0 ; i < x.size(); i++) {
fill (0,255,0);
rect(x.get(i)*bs, y.get(i)*bs, bs, bs);
}
if(!gameover) {
fill(255,0,0);
rect(applex*bs, appley*bs, bs, bs);
if(frameCount%5==0) {
x.add(0,x.get(0) + dx[dir]);
y.add(0,y.get(0) + dy[dir]);
if(x.get(0) < 0 || y.get(0) < 0 || x.get(0) >= w || y.get(0) >= h) gameover = true;
for(int i = 1; i < x.size(); i++) if(x.get(0) == x.get(i) && y.get(0) == y.get(i)) gameover = true;
if(x.get(0)==applex && y.get(0)==appley) {
applex = (int)random(0,w);
appley = (int)random(0,h);
}else {
x.remove(x.size()-1);
y.remove(y.size()-1);
}
}
} else {
fill(0);
textSize(30);
text("GAME OVER. Press Space to Play Again", 20, height/2);
if(keyPressed && key == ' ') {
x.clear(); //Clear array list
y.clear(); //Clear array list
x.add(5);
y.add(5);
gameover = false;
}
}
if (keyPressed == true) {
int newdir = key=='s' ? 0 : (key=='w' ? 1 : (key=='d' ? 2 : (key=='a' ? 3 : -1)));
if(newdir != -1 && (x.size() <= 1 || !(x.get(1) ==x.get(0) + dx[newdir] && y.get (1) == y.get(0) + dy[newdir]))) dir = newdir;
}
}
You need to break your problem down into smaller steps:
Step one: Can you store the difficulty in a variable? This might be an int that keeps track of a level, or a boolean that switches between easy and hard. Just hardcode the value of that variable for now.
Step two: Can you write your code so it changes behavior based on the difficulty level? Use the variable you created in step one. You might use an if statement to check the difficulty level, or maybe the speed increases over time. It's completely up to you. Start out with a hard-coded value. Change the value to see different behaviors.
Step three: Can you programatically change that value? Maybe this requires a settings screen where the user chooses the difficulty, or maybe it gets more difficult over time. But you have to do the first two steps before you can start this step.
If you get stuck on a specific step, then post an MCVE and we'll go from there.

C++ operator overloading causing segmentation fault

below is the code which is giving segmentation fault for I don't know what reason. In an attempt to overload ^ operator, I am getting segmentation fault.
Here is my code.
#include <iostream>
#include <algorithm>
using namespace std;
class bigint {
public:
char val[1000000];
int msdindex;
bool iszero;
bigint( int i ) {
if( i == 0 )
iszero = true;
else {
iszero = false;
msdindex = -1;
while( i > 0 ) {
msdindex++;
val[ msdindex ] = i % 10;
i /= 10;
}
}
}
bigint( const bigint& bi ) {
msdindex = bi.msdindex;
iszero = bi.iszero;
for( int i = 0; i <= msdindex; i++ )
val[i] = bi.val[i];
}
};
bigint operator^( bigint k, int n ) {
if( n == 1 )
return bigint(k);
bigint half = k^(n/2);
return half;
}
int main()
{
bigint bi = bigint( 999 );
bigint di = bi ^ 4;
return 0;
}
Segmentation fault is in the overloaded function ^ and I am clueless of the reason. gdb says this.
Traceback (most recent call last):
File "/usr/share/gdb/auto-load/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19-gdb.py", line 63, in
from libstdcxx.v6.printers import register_libstdcxx_printers
ImportError: No module named 'libstdcxx'
Program received signal SIGSEGV, Segmentation fault.
0x0000000000400749 in operator^(bigint, int) ()
Please help.
You are running out of memory, due to which you program crashes everytime. Reducing the status allocation of char in bigint to a smaller value will work fine.
Or use dynamic memory allocation in case you want huge char array, that will solve your problem.
Hope this helps.
class bigint {
public:
char *val;//[1000000];
int msdindex;
bool iszero;
bigint( int i ) {
if( i == 0 )
iszero = true;
else {
iszero = false;
msdindex = -1;
val = new char[1000000];
while( i > 0 ) {
msdindex++;
val[ msdindex ] = i % 10;
i /= 10;
}
}
}
bigint( const bigint& bi ) {
msdindex = bi.msdindex;
iszero = bi.iszero;
val = new char[1000000];
for( int i = 0; i <= msdindex; i++ )
val[i] = bi.val[i];
}
};
Don't forget to write destructor for this to deallocate this dynamically allocated memory. Cheers.

How to set order few pips above order initiation bar in MQL4

I would like to create a stoploss order that will be placed above the high of the previous order's initiation bar in case this is a Sell order OR below the low of the previous order's initiation bar in case this is a Buy order.
Here is a picture to illustrate the issue ( the example depicts a sell order case ):
Any idea how to do that? The code below works fine if I use stoploss that is fixed. If I replace the stoploss with variables that are based on High or Low no orders are fired.
Here is my code:
//| Expert initialization function |
//+------------------------------------------------------------------+
/* -----------------------------------------------------------------------------
KINDLY RESPECT THIS & DO NOT MODIFY THE EDITS AGAIN
MQL4 FORMAT IS NOT INDENTATION SENSITIVE,
HAS IDE-HIGHLIGHTING
AND
HAS NO OTHER RESTRICTIVE CONDITIONS ----------- THIS CODING-STYLE HELPS A LOT
FOR BOTH
EASY & FAST
TRACKING OF NON-SYNTACTIC ERRORS
AND
IMPROVES FAST ORIENTATION
IN ALGORITHM CONSTRUCTORS' MODs
DURING RAPID PROTOTYPING
IF YOU CANNOT RESIST,
SOLVE RATHER ANY OTHER PROBLEM,
THAT MAY HELP SOMEONE ELSE's POST, THX
------------------------------------------- KINDLY RESPECT
THE AIM OF StackOverflow
------------------------------------------- TO HELP OTHERS DEVELOP UNDERSTANDING,
THEIRS UNDERSTANDING, OK? */
extern int StartHour = 14;
extern int TakeProfit = 70;
extern int StopLoss = 40;
extern double Lots = 0.01;
extern int MA_period = 20;
extern int MA_period_1 = 45;
extern int RSI_period14 = 14;
extern int RSI_period12 = 12;
void OnTick() {
static bool IsFirstTick = true;
static int ticket = 0;
double R_MA = iMA( Symbol(), Period(), MA_period, 0, 0, 0, 1 );
double R_MA_Fast = iMA( Symbol(), Period(), MA_period_1, 0, 0, 0, 1 );
double R_RSI14 = iRSI( Symbol(), Period(), RSI_period14, 0, 0 );
double R_RSI12 = iRSI( Symbol(), Period(), RSI_period12, 0, 0 );
double HH = High[1];
double LL = Low[ 1];
if ( Hour() == StartHour ) {
if ( IsFirstTick == true ) {
IsFirstTick = false;
bool res1 = OrderSelect( ticket, SELECT_BY_TICKET );
if ( res1 == true ) {
if ( OrderCloseTime() == 0 ) {
bool res2 = OrderClose( ticket, Lots, OrderClosePrice(), 10 );
if ( res2 == false ) {
Alert( "Error closing order # ", ticket );
}
}
}
if ( High[1] < R_MA
&& R_RSI12 > R_RSI14
&& R_MA_Fast >= R_MA
){
ticket = OrderSend( Symbol(),
OP_BUY,
Lots,
Ask,
10,
Bid - LL * Point * 10,
Bid + TakeProfit * Point * 10,
"Set by SimpleSystem"
);
}
if ( ticket < 0 ) {
Alert( "Error Sending Order!" );
}
else {
if ( High[1] > R_MA
&& R_RSI12 > R_RSI14
&& R_MA_Fast <= R_MA
){
ticket = OrderSend( Symbol(),
OP_SELL,
Lots,
Bid,
10,
Ask + HH * Point * 10,
Ask - TakeProfit * Point * 10,
"Set by SimpleSystem"
);
}
if ( ticket < 0 ) {
Alert( "Error Sending Order!" );
}
}
}
}
else {
IsFirstTick = true;
}
}
Major issue
Once having assigned ( per each Market Event Quote Arrival )
double HH = High[1],
LL = Low[ 1];
Your instruction to OP_SELL shall be repaired:
ticket = OrderSend( Symbol(),
OP_SELL,
Lots,
Bid,
10,
// ----------------------v--------------------------------------
// Ask + HH * 10 * Point,
// intention was High[1] + 10 [PT]s ( if Broker allows ), right?
NormalizeDouble( HH + 10 * Point,
Digits // ALWAYS NORMALIZE FOR .XTO-s
),
// vvv----------------------------------------------------------
// Ask - TakeProfit * Point * 10, // SAFER TO BASE ON BreakEvenPT
NormalizeDouble( Ask
- TakeProfit * Point * 10,
Digits // ALWAYS NORMALIZE FOR .XTO-s
),
"Set by SimpleSystem"
);
Symmetrically review and modify the OP_BUY case.
For Broker T&C collisions ( these need not get reflected in backtest ) review:
MarketInfo( _Symbol, MODE_STOPLEVEL )
MarketInfo( _Symbol, MODE_FREEZELEVEL )
or inspect in the MT4.Terminal in the MarketWatch aMouseRightClick Symbols -> Properties for STOPLEVEL distance.
Minor Issue
Review also your code for OrderClose() -- this will fail due to having wrong Price:
// ---------------------------------------------vvvvv----------------------------
bool res2 = OrderClose( ticket, Lots, OrderClosePrice(), 10 ); # was db.POOL()-SELECT'd

SURF error while tracking object

I am trying to find an object in the videos by calling SURF function for each frame ...
this is the SURF Function
{
void Identify_SURF_Frame (Mat img_object , Mat img_scene , CvRect in_box)
{
//-- Step 1: Detect the keypoints using SURF Detector
int minHessian = 1;
SurfFeatureDetector detector( minHessian , 15 , 3 );
std::vector<KeyPoint> keypoints_object, keypoints_scene;
detector.detect( img_object, keypoints_object );
detector.detect( img_scene, keypoints_scene );
//-- Step 2: Calculate descriptors (feature vectors)
SurfDescriptorExtractor extractor;
Mat descriptors_object, descriptors_scene;
extractor.compute( img_object, keypoints_object, descriptors_object );
extractor.compute( img_scene, keypoints_scene, descriptors_scene );
//-- Step 3: Matching descriptor vectors using FLANN matcher
//FlannBasedMatcher matcher;
BruteForceMatcher < L2 < float > > matcher;
//BFMatcher matcher( cv::NORM_L2SQR , false );
std::vector< DMatch > matches;
matcher.match( descriptors_object, descriptors_scene, matches );
double max_dist = 0; double min_dist = 100;
//-- Quick calculation of max and min distances between keypoints
for( int i = 0; i < descriptors_object.rows; i++ )
{
double dist = matches[i].distance;
if( dist < min_dist ) min_dist = dist;
if( dist > max_dist ) max_dist = dist;
}
//-- Draw only "good" matches (i.e. whose distance is less than 3*min_dist )
std::vector< DMatch > good_matches;
for( int i = 0; i < descriptors_object.rows; i++ )
{
if( matches[i].distance < 4 * min_dist )
{
good_matches.push_back( matches[i]);
}
}
Mat img_matches;
drawMatches( img_object, keypoints_object, img_scene, keypoints_scene, good_matches, img_matches, Scalar::all(-1), Scalar::all(-1), vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );
//-- Localize the object
std::vector<Point2f> obj;
std::vector<Point2f> scene;
for( int i = 0; i < good_matches.size(); i++ )
{
//-- Get the keypoints from the good matches
obj.push_back( keypoints_object[ good_matches[i].queryIdx ].pt );
scene.push_back( keypoints_scene[ good_matches[i].trainIdx ].pt );
}
Mat H = findHomography( obj, scene, CV_RANSAC );
//-- Get the corners from the image_1 ( the object to be "detected" )
std::vector<Point2f> obj_corners(2);
obj_corners[0] = cvPoint(0,0);
obj_corners[1] = cvPoint( img_object.cols, 0 );
//obj_corners[2] = cvPoint( img_object.cols, img_object.rows );
//obj_corners[3] = cvPoint( 0, img_object.rows );
std::vector<Point2f> scene_corners(2);
perspectiveTransform( obj_corners, scene_corners, H);
int x1 , x2 , y1 , y2 ;
x1 = scene_corners[0].x + Point2f( img_object.cols, 0).x ;
y1 = scene_corners[0].y + Point2f( img_object.cols, 0).y ;
x2 = scene_corners[0].x + Point2f( img_object.cols, 0).x + in_box.width ;
y2 = scene_corners[0].y + Point2f( img_object.cols, 0).y + in_box.height ;
rectangle(img_matches , cvPoint(x1, y1) , cvPoint(x2, y2) , Scalar( 255, 255, 255), 1 );
// square is the global CvRect to use it in main
square.x = x1 - in_box.width ;
square.y = y1 ;
square.width = in_box.width ;
square.height = in_box.height ;
//-- Show detected matches
imshow( "Good Matches & Object detection", img_matches );
}
}
using this function I am trying to draw fixed size square around the object when I find it
the problem is .... some time I got this error which I do not what it mean .. sometime the program work fine without this error .. when this error happen the program scratch
{
OpenCV Error: Assertion failed (count >= 4) in cvFindHomography, file /Users/seereen2004/Desktop/OpenCV-2.4.3/modules/calib3d/src/fundam.cpp, line 235
terminate called after throwing an instance of 'cv::Exception'
what(): /Users/seereen2004/Desktop/OpenCV-2.4.3/modules/calib3d/src/fundam.cpp:235: error: (-215) count >= 4 in function cvFindHomography
Program received signal: “SIGABRT”.
sharedlibrary apply-load-rules all
}
any explanation please ?
Thanks in Advance
Something like that may be when you have too few good_matches (<=4). You need skip this frames.

Resources