animation from 3DS to OpenGL - c

I am trying to export a 3ds animation to OpenGL and I want to go to the next frame little by little. To do that I use 3ds file with 100 keys so if I do not make mistakes it is ok.
To run my animation I use the lib3ds_file_eval statement but it seems I am doing a mistake
Here is how I do that :
void animationTimer(int value) {
if (g_haltAnimation != 0) {
lib3ds_file_eval(g_scenes3DS[ANIMATED_KART_ID].lib3dsfile, g_currentFrame);
g_currentFrame = (g_currentFrame + 1) % g_scenes3DS[ANIMATED_KART_ID].lib3dsfile->frames;
glutTimerFunc(10, animationTimer, 0);
}
}
So it is quite simple. I put the lib3dsfile of my scene in parameter and the number of the next frame. And when I check the transformation matrix in nodes, it does not change and I can not find why.
I noticed that current_frame in lib3dsFile does not change too, I do not know if it is normal or not.

It is normal behaviour that current_frame in the file does not change. However the matrices of at least some nodes should change for a non-trivial animation.
Did you check the nodes by doing the following?
for (Lib3dsNode* p = g_scenes3DS[ANIMATED_KART_ID].lib3dsfile->nodes; p != 0; p = p->next )
{
// check p->matrix here
}
Make sure to check every matrix because some (most?) nodes probably won't move in a kart animation.

Related

How do I correctly create a copy of an array in C or set a reference to one?

so, I'm very new to C, coming from a Java/C# background and I can't quite wrap my head around it so far.
What I'm trying to do is program a microcontroller (Adafruit Feather running an atmega32u4 in this case) to pose as a USB-coupled controller for Nintendo Switch and run automated commands.
The project I'm trying to expand upon is using a struct array of commands like this:
typedef struct {
Buttons_t button;
uint16_t duration; // 1 equals 0.025s on ATmega32u4 => 1s = 40
} command;
static const command loop[] = {
// do stuff
{ NOTHING, 150 },
{ TRIGGERS, 15 }, { NOTHING, 150 },
{ TRIGGERS, 15 }, { NOTHING, 150 },
{ A, 5 }, { NOTHING, 250 }
};
Now initially this was all there was to it, the program would loop through the commands, send a button to the console and "hold" it for the defined period of time. When the program ran to the end of the array, it would simply reset the index and start anew.
Now I'm trying to send different commands to the console, based on a few easy if..else queries. Specifically, the program will start with a day, month and year variable (the date the Switch console is currently set to) and roll days forward individually to get to a set date in the future. To this end, I want to check at every 'step' if the date +1 day is valid as described in this tutorial and based on the result either roll one day, one day and one month or one day, one month and one year forward. Then I want it to end after a set amount of days.
I wrote several arrays of commands to represent the different steps needed for setting up the controller, moving to where it's supposed to loop, rolling a day, a month or a year like this:
static const command setupController[] = {
// Setup controller
...
};
static const command moveToLoop[] = {
// Go into date settings
...
};
static const command rollDay[] = {
//roll to next day
...
};
static const command rollMonth[] = {
//roll to next month
...
};
static const command rollYear[] = {
//roll to next year
...
};
And another array I want to copy those to like this:
#define COMMANDMAXSIZE 100
static command activeCommand[COMMANDMAXSIZE];
I know this is (extremely) wasteful of memory, but I'm definitely not good enough at C to come up with fancier, more conservative solutions yet.
Then I go into my program, which looks like this:
int main(void) {
SetupHardware(); //Irrelevant, because it is exactly like I downloaded it and it works even with the bumbling changes I've made
GlobalInterruptEnable(); //Ditto
RunOnce(setupController);
RunOnce(moveToLoop);
while (daysSkipped != stopDay)
{
if (datevalid((dayOfMonth + 1), month, year)) {
dayOfMonth++;
RunOnce(rollDay);
}
else if (datevalid(1, (month + 1), year)) {
dayOfMonth = 1;
month++;
RunOnce(rollMonth);
}
else if (datevalid(1, 1, (year + 1))) {
dayOfMonth = 1;
month = 1;
year++;
RunOnce(rollYear);
}
daysSkipped++;
}
}
and finally (I swear I'll be done soon), the start of RunOnce looks like this
void RunOnce(command stepsToRun[]) {
memcpy(activeCommand, stepsToRun, sizeof(activeCommand)); //set the setup commands to be active
activeBounds = sizeof(stepsToRun) / sizeof(stepsToRun[0]);
...
Later in the program, the task that translates commands into button presses for the console actually runs one fixed array, so I figured I'd just "mark" the commands to run as active, and only ever run the active array. Only, it doesn't work as expected:
The program runs, sets up the controller, moves to the date settings and indeed starts to roll a date, but then, regardless if the next day is valid or not, it rolls forward a month, then a year and then it gets stuck moving the simulated analog stick upwards and pressing A indefinitely.
I figure the problem lies in my memcpy to overwrite the active array with the steps I want to run next, but I can't think of a way to solve it. I tried writing a function that was supposed to overwrite the active array element by element using a for loop, but this way the controller wouldn't even set itself up correctly and effectively nothing happened. Usually with any kind of output capabilities I'd try to fit in prints at points of interest, but I have virtually no way of getting feedback on my microcontroller.
Any help would be greatly appreciated.
Ignoring that doing a hard copy of the data is incredibly slow and wasteful, it is also incorrect indeed.
memcpy(activeCommand, stepsToRun, sizeof(activeCommand));
Here you need to copy the size of the data you pass on, not the size of the target buffer! Right now you end up copying more data than you have, because all of these declarations static const command rollDay[] etc get a variable size depending on the number of items in the initializer list.
The quick & dirty fix to your immediate problem would be to pass along the size:
void RunOnce(size_t size, command stepsToRun[size])
{
memcpy(activeCommand, stepsToRun, size);
and then call this function with RunOnce(sizeof rollDay, rollDay); etc.
The activeBounds = sizeof(stepsToRun) / sizeof(stepsToRun[0]); part is also incorrect but not the immediate reason for the bug. See How to find the 'sizeof' (a pointer pointing to an array)? and What is array to pointer decay? etc.
When you pass array to function it decays to a pointer.
RunOnce(rollYear);
Thus
void RunOnce(command stepsToRun[]) {
memcpy(activeCommand, stepsToRun, sizeof(activeCommand)); //set the setup commands to be active
activeBounds = sizeof(stepsToRun) / sizeof(stepsToRun[0]);
}
sizeof(stepsToRun) doesn't yield the correct result as you expected, since it is now sizeof(pointer) in function.
You will have to pass the size of the array as an extra argument to RunOnce function.

CSFML Vertex Array and drawing

It's been a few weeks i've been working a project for my school and I now need to work on particles. I've been looking at vertices and it looks like to be a good way to make them.
I've started by trying to print at least one vertex on the screen and to print it, but I don't know what I'm doing wrong.
CSFML is a very restricted library as not many people use it, so trying to find SFML examples and to figure out the derivates of the functions to C is quite hard and giving me some troubles.
Here's my code :
{
sfVertex a;
sfVector2f apos = {200, 100};
a.color = sfRed;
a.position = apos;
sfVertexArray *array = sfVertexArray_create();
sfVertexArray_setPrimitiveType(array, sfPoints);
sfVertexArray_append(array, a);
sfRenderWindow_drawVertexArray(window, array, 0);
}
In this example, I'm trying to create a vertex, give it a position, a color, and then create a vertex array that takes point vertices and to append my vertex to the vertex array. I think the only problem here is to print it on the screen, as sfRenderWindow_drawVertexArray(window, array, 0); doesn't print anything, and if I put the render state to 1 my program just crashes before even opening my window.
I tried to find examples and explanations about this function but I'm pretty much lost now.
I think your error was that you did not set sfPoints in your code. Here is a simple code that draws 4 points.
#include <iostream>
#include <SFML/Graphics.hpp>
int main(){
sf::RenderWindow window(sf::VideoMode(200, 200), "SFML works!");
while (window.isOpen()){
sf::Event event;
while (window.pollEvent(event)){
if (event.type == sf::Event::Closed)
window.close();
}
sf::VertexArray vertexArray (sf::Points, 4);
vertexArray[0].position = sf::Vector2f(10, 10);
vertexArray[1].position = sf::Vector2f(10, 20);
vertexArray[2].position = sf::Vector2f(20, 10);
vertexArray[3].position = sf::Vector2f(20, 20);
// Set colour for all vertices
for(int i = 0; i < 4.; i++){
vertexArray[i].color=sf::Color::Yellow;
}
window.clear();
window.draw(vertexArray);
window.display();
}
return 0;
}

Raising RAM in load BMP function SDL

I'm using SDL to code a simple game, and i have a big problem - i'm trying to do some animations with function,
in the fuction i call static int which keeps raising every game tick, and dependant on value of static int i change my variable image (with image=SDL_LoadBMP(myfile)), it's working great, but after 10 minutes of running a program, which had been working with 50MB of memory before without this really simple animation, ram usage of my program is starting to get bigger and bigger, and as i said, after 10 minutes it's 3GB and keeps raising every animation occur(so, like every 3 seconds).
Weird thing is also that i have other image which animation is a little bit simplier - i change my image upon clicking any arrow (still in main), and then call function, so after a second it gives back the initial image to a variable(it's giving image back in function), and it's working great - with that i mean - even if i keep clicking arrows, memory usage is constant.
my function looks like that:
void func(obj* image)
{
static int time1;
time1++;
if(time1>1000)
{
time1=0;
SDL_FreeSurface(image->image); //this doesn't change anything
image->image=SDL_LoadBMP("path");
}
else if(time1>800)
image->image=SDL_LoadBMP("path2");
else if(time1>600)
image->image=SDL_LoadBMP("path3");
else if(time1>400)
image->image=SDL_LoadBMP("path4");
}
typedef struct {
SDL_Surface* image;
}obj;
int main()
{
obj struct;
func(&struct);
}
ofc it's fulfilled with all this SDL library calls to make a window etc
https://i.ibb.co/YBcvjnF/Bez-tytu-u.png
If I understand correctly you're making SDL_Surface* over and over again, you never call SDL_FreeSurface()(info).
You need to load a some point all the BMP needed to play the animation into SDL_Surface* then reuse these BMP(s).
In your main (or into an init function) you need to store into an array or pointers the BMP images.
// Somewhere on one of your struct
SDL_Surface *animationImages[4];
// Then in an init function you do
animationImages[0] = SDL_LoadBMP("path");
animationImages[1] = SDL_LoadBMP("path2");
animationImages[2] = SDL_LoadBMP("path3");
animationImages[3] = SDL_LoadBMP("path4");
// And finally
void func(obj* image) {
static int time1;
time1++;
if (time1>1000) {
time1 = 0;
image->image = animationImages[0];
} else if (time1>800) {
image->image = animationImages[1];
} else if (time1>600) {
image->image = animationImages[2];
} else if (time1>400) {
image->image = animationImages[3];
}
}
And before the end of your game or when you don't need these animationImages anymore call SDL_FreeSurface() for each SDL_Surface* you have created.
// In a specific function used to clean up allocated stuff you do
SDL_FreeSurface(animationImages[0]);
SDL_FreeSurface(animationImages[1]);
SDL_FreeSurface(animationImages[2]);
SDL_FreeSurface(animationImages[3]);

Implementing multi-threading in an already existing chess engine in C

I want to know if its possible to modify an existing chess engine in C that works without multi-threading to be able to support multi-threading. I have no experience in this subject and would appreciate some guidance.
EDIT: To be more specific, is there anything I can add to my implementation of negamax to make it multi-thread compatible? :
static double alphaBetaMax(double alpha, double beta, int depthleft, game_t game, bool player)
{
move_t *cur;
move_t *tmp;
double score = 0;
bool did_move = false;
cur = getAllMoves(game, player);
if(cur == NULL) /*/ check mate*/
return -9999999*(player*2-1);
tmp = firstMove;
firstMove = 0;
while (cur != NULL)
{
game_t copy;
if(depthleft<=0 && !isCapture(game, cur)) { /* Quiescence search */
cur = cur->next;
continue;
}
did_move = true;
copyGame(game, &copy);
makeMove(&copy, *cur);
firstMove = NULL;
score = -alphaBetaMax(-beta, -alpha, depthleft - 1, copy, !player);
if(board_count > MAX_BOARDS)
break;
freeGame(copy);
if(score > alpha)
alpha = score;
if (beta <= alpha)
break;
cur = cur->next;
}
firstMove=tmp;
freeMoves();
if(!did_move)
alpha = evaluate(game)*(player*2-1);
return alpha;
}
A fast chess engine relies on two things: Caching the evaluation of positions, and the alpha/beta strategy. Caching positions and making it thread safe and fast is hard. The alpha/beta strategy relies on the seemingly best move being completely evaluated before you start evaluating other moves. This also makes it tough to use multiple threads.
Beginner composer to Mozart: "Can you tell me how to compose a symphony"? Mozart to beginner: "Maybe at your young age you should try something easier first. " Beginner to Mozart: "But you wrote symphonies when you were much younger than I am now. " Mozart to beginner: "True, but I didn't have to ask anyone".
The Alpha-Beta pruning is inherently single-threaded in nature. There's been successful approaches using variations of Dynamic Tree Splitting which basically means searching various branches at the same time. However the likelihood (in a well tuned engine) that next branch will be searched (or beta-cut) does not usually outweigh the other parallelism bottlenecks like memory waits.
I would suggest, first modify your search to a "re-search" algorithm like NegaScout or PVS which with small code changes will give good improvements over your current pure Alpha-Beta, then secondly fine-tune your move ordering to yield efficient beta-cut.
Thereafter you could try to split the tree based on beta-cut chances. Typically there would be higher chance of cutoff when a move is found in the transposition-table or a killer move and lesser chance when starting to search bad captures and quiet moves.
Take a look at CPW for some thoughts on it and the YBWC algorithm.
Young Brothers Wait Concept
I'm currently writing a c++ chess engine and I have made a quite simple but not optimal solution:
First I'm generating all moves in the form of a list of structs
I start n threads which repeatedly grab "jobs" from the list
do their search and write back the result into the struct. When the
list is empty, a thread kills itself.
In the general search function I join the threads and loop through the results afterwards.
Is this approach most efficient?
As currently the focus on searching the most relevant moves first but you'll eventually look at all moves and also hardly get a cutoff at depth one but works fine
Simple to implement and in any case better than a "one-cpu" search. Even if one move takes way more time - it's running on one cpu, like back then :D
Maybe start out with that

Print doesn't show in printed array although specified

I'm working a simple candy crush game for my year 1 assignment.
I am at this stage where I need to show my self-made simple marker( *box made of '|' and '_'* ) on the center of the board ( board[5][5] ) once the program is executed.
Here is the current code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
//FUNCTION: Draw the Board
int drawBoard()
{
//Declare array size
int board[9][9];
//initialize variables
int rows, columns, randomNumber, flag;
//random number seed generator
srand(time(NULL));
for ( rows = 0 ; rows < 9 ; rows++ )
{
for ( columns = 0 ; columns < 9 ; columns++ )
{
flag = 0;
do
{
//generate random numbers from 2 - 8
randomNumber = rand() %7 + 2;
board[rows][columns] = randomNumber;
//Checks for 2 adjacent numbers.
if ( board[rows][columns] == board[rows - 1][columns] || board[rows][columns] == board[rows][columns - 1] )
{
flag = 0;
continue;
}
else
{
flag = 1;
printf( " %d ", board[rows][columns] );
}
} while ( flag == 0 );
}//end inner for-loop
printf("\n\n");
}//end outer for-loop
//call FUNCTION marker() to display marker around board[5][5]
marker( board[5][5] );
}//end FUNCTION drawBoard
//FUNCTION: Mark the surrounding of the number with "|" and "_" at board[5][5]
void marker( int a )
{
printf( " _ \n" );
printf( "|%c|\n", a );
printf( " _ \n" );
}
int main()
{
drawBoard();
}
At the end of function drawBoard(), I placed the code marker( board[5][5] ).
This should have printed the markers around the number printed at coordinate board[5][5]..but for some reason it displays right after the board has been printed.
So why doesn't it print at that coordinate although I specified it at board[5][5]?
What could be the problem here?
so in your marker function you need to pass the board and the coordinate you want to print at
void marker( int x, int y, int** board )
{
board[x][y-1]="_";
board[x-1][y]="|";
board[x+1][y]="|";
board[x][y+1]="_";
}
then after the call to marker(5,5,board), call drawboard again
my code's a bit off but that's the logic, except you need to check for the case that the marker is at the edge of the board
in other words, you need to keep board around, and any time you make a change to it, clear the screen and print the whole board out again.
There is no persistent drawing in the way that you are doing this. You are just printing straight to the shell/command prompt. The way that you trying to do things will not work. You can't edit something drawn to the prompt after you have drawn it, you need to basically clear the screen and then draw again but with your indicated maker.
I don't know if you are able to use libraries in your assignment, but a very good library that WILL let you do is ncurses
EDIT Full rewrite of answer
Drawing Things On Top of One Another In CMD
Alright, I had some downtime at work, so I wrote a project to do what you need and I'm going to post code and explain what it does and why you need it along the way.
First thin that you are going to need a basically a render buffer or a render context. Whenever you are programming in a graphics API such as OpenGL, you don't just render straight to the screen, you render each object that you have to a buffer that rasterizes your content and turns it into pixels. Once it's in that form, the API shoves the rendered picture onto the screen. We are going to take a similar approach where instead of drawing to a pixel buffer on the GPU, we are going to draw to a character buffer. Think about each character as a pixel on the screen.
Here is a pastebin of the complete source:
Complete Source of Project
RenderContext
Our class to do this will be the RenderContext class. It has fields to hold width and height as well as an array of chars and a special char that we fill our buffer with whenever we clear it.
This class simply holds an array and functions to let us render to it. It makes sure that when we draw to it, we are within bounds. It is possible for an object to try to draw outside of the clipping space (off screen). However, whatever is drawn there is discarded.
class RenderContext {
private:
int m_width, m_height; // Width and Height of this canvas
char* m_renderBuffer; // Array to hold "pixels" of canvas
char m_clearChar; // What to clear the array to
public:
RenderContext() : m_width(50), m_height(20), m_clearChar(' ') {
m_renderBuffer = new char[m_width * m_height];
}
RenderContext(int width, int height) : m_width(width), m_height(height), m_clearChar(' ') {
m_renderBuffer = new char[m_width * m_height];
}
~RenderContext();
char getContentAt(int x, int y);
void setContentAt(int x, int y, char val);
void setClearChar(char clearChar);
void render();
void clear();
};
The two most important functions of this class are setContentAt and render
setContentAt is what an object calls to fill in a "pixel" value. To make this a little more flexible, our class uses a pointer to an array of chars rather than a straight array (or even a two dimensional array). This lets us set the size of our canvas at runtime. Because of this, we access elements of this array with x + (y * m_width) which replaces a two dimensional dereference such as arr[i][j]
// Fill a specific "pixel" on the canvas
void RenderContext::setContentAt(int x, int y, char val) {
if (((0 <= x) && (x < m_width)) && ((0 <= y) && (y < m_height))) {
m_renderBuffer[(x + (y * m_width))] = val;
}
}
render is what actually draws to the prompt. All it does is iterate over all the "pixels" in it's buffer and place them on screen and then moves to the next line.
// Paint the canvas to the shell
void RenderContext::render() {
int row, column;
for (row = 0; row < m_height; row++) {
for (column = 0; column < m_width; column++) {
printf("%c", getContentAt(column, row));
}
printf("\n");
}
}
I_Drawable
Our next class is an Interface that lets us contract with objects that they can draw to our RenderContext. It is pure virtual because we don't want to actually be able to instantiate it, we only want to derive from it. It's only function is draw which accepts a RenderContext. Derived classes use this call to receive the RenderContext and then use RenderContext's setContentAt to put "pixels" into the buffer.
class I_Drawable {
public:
virtual void draw(RenderContext&) = 0;
};
GameBoard
The first class to implement the I_Drawable, thus being able to render to our RenderContext, is the GameBoard class. This is where a majority of the logic comes in. It has fields for width, height, and a integer array that holds the values of the elements on the board. It also has two other fields for spacing. Since when you draw your board using your code, you have spaces between each element. We don't need to incorporate this into the underlying structure of the board, we just need to use them when we draw.
class GameBoard : public I_Drawable {
private:
int m_width, m_height; // Width and height of the board
int m_verticalSpacing, m_horizontalSpacing; // Spaces between each element on the board
Marker m_marker; // The cursor that will draw on this board
int* m_board; // Array of elements on this board
void setAtPos(int x, int y, int val);
void generateBoard();
public:
GameBoard() : m_width(10), m_height(10), m_verticalSpacing(5), m_horizontalSpacing(3), m_marker(Marker()) {
m_board = new int[m_width * m_height];
generateBoard();
}
GameBoard(int width, int height) : m_width(width), m_height(height), m_verticalSpacing(5), m_horizontalSpacing(3), m_marker(Marker()) {
m_board = new int[m_width * m_height];
generateBoard();
}
~GameBoard();
int getAtPos(int x, int y);
void draw(RenderContext& renderTarget);
void handleInput(MoveDirection moveDirection);
int getWidth();
int getHeight();
};
It's key functions are generateBoard, handleInput, and the derived virtual function draw. However, do note that in its constructor it creates a new int array and gives it to its pointer. Then its destructor automatically removes the allocated memory whenever the board goes away.
generateBoard is what we use to actual create the board and fill it with numbers. It will iterate over each location on the board. Each time, it will look at the elements directly to the left and above and store them. Then it will generate a random number until the number it generates does not match either of the stored elements, then it stores the number in the array. I rewrote this to get rid of the flag usage. This function gets called during the construction of the class.
// Actually create the board
void GameBoard::generateBoard() {
int row, column, randomNumber, valToLeft, valToTop;
// Iterate over all rows and columns
for (row = 0; row < m_height; row++) {
for (column = 0; column < m_width; column++) {
// Get the previous elements
valToLeft = getAtPos(column - 1, row);
valToTop = getAtPos(column, row - 1);
// Generate random numbers until we have one
// that is not the same as an adjacent element
do {
randomNumber = (2 + (rand() % 7));
} while ((valToLeft == randomNumber) || (valToTop == randomNumber));
setAtPos(column, row, randomNumber);
}
}
}
handleInput is what deals with moving the cursor around on the board. It's basically a freebie and your next step after getting the cursor to draw over the board. I needed a way to test the drawing. It accepts an enumeration that we switch on to know where to move our cursor to next. If you maybe wanted to have your cursor wrap around the board whenever you reach an edge, you would want to do that here.
void GameBoard::handleInput(MoveDirection moveDirection) {
switch (moveDirection) {
case MD_UP:
if (m_marker.getYPos() > 0)
m_marker.setYPos(m_marker.getYPos() - 1);
break;
case MD_DOWN:
if (m_marker.getYPos() < m_height - 1)
m_marker.setYPos(m_marker.getYPos() + 1);
break;
case MD_LEFT:
if (m_marker.getXPos() > 0)
m_marker.setXPos(m_marker.getXPos() - 1);
break;
case MD_RIGHT:
if (m_marker.getXPos() < m_width - 1)
m_marker.setXPos(m_marker.getXPos() + 1);
break;
}
}
draw is very important because it's what gets the numbers into the RenderContext. To summarize, it iterates over every element on the board, and draws in the correct location on the canvas placing an element under the correct "pixel". This is where we incorporate the spacing. Also, take care and note that we render the cursor in this function.
It's a matter of choice, but you can either store a marker outside of the GameBoard class and render it yourself in the main loop (this would be a good choice because it loosens the coupling between the GameBoard class and the Marker class. However, since they are fairly coupled, I chose to let GameBoard render it. If we used a scene graph, as we probably would with a more complex scene/game, the Marker would probably be a child node of the GameBoard so it would be similar to this implementation but still more generic by not storing an explicit Marker in the GameBoard class.
// Function to draw to the canvas
void GameBoard::draw(RenderContext& renderTarget) {
int row, column;
char buffer[8];
// Iterate over every element
for (row = 0; row < m_height; row++) {
for (column = 0; column < m_width; column++) {
// Convert the integer to a char
sprintf(buffer, "%d", getAtPos(column, row));
// Set the canvas "pixel" to the char at the
// desired position including the padding
renderTarget.setContentAt(
((column * m_verticalSpacing) + 1),
((row * m_horizontalSpacing) + 1),
buffer[0]);
}
}
// Draw the marker
m_marker.draw(renderTarget);
}
Marker
Speaking of the Marker class, let's look at that now. The Marker class is actually very similar to the GameBoard class. However, it lacks a lot of the logic that GameBoard has since it doesn't need to worry about a bunch of elements on the board. The important thing is the draw function.
class Marker : public I_Drawable {
private:
int m_xPos, m_yPos; // Position of cursor
public:
Marker() : m_xPos(0), m_yPos(0) {
}
Marker(int xPos, int yPos) : m_xPos(xPos), m_yPos(yPos) {
}
void draw(RenderContext& renderTarget);
int getXPos();
int getYPos();
void setXPos(int xPos);
void setYPos(int yPos);
};
draw simply puts four symbols onto the RenderContext to outline the selected element on the board. Take note that Marker has no clue about the GameBoard class. It has no reference to it, it doesn't know how large it is, or what elements it holds. You should note though, that I got lazy and didn't take out the hard coded offsets that sort of depend on the padding that the GameBoard has. You should implement a better solution to this because if you change the padding in the GameBoard class, your cursor will be off.
Besides that, whenever the symbols get drawn, they overwrite whatever is in the ContextBuffer. This is important because the main point of your question was how to draw the cursor on top of the GameBoard. This also goes to the importance of draw order. Let's say that whenever we draw our GameBoard, we drew a '=' between each element. If we drew the cursor first and then the board, the GameBoard would draw over the cursor making it invisible.
If this were a more complex scene, we might have to do something fancy like use a depth buffer that would record the z-index of an element. Then whenever we drew, we would check and see if the z-index of the new element was closer or further away than whatever was already in the RenderContext's buffer. Depending on that, we might skip drawing the "pixel" altogether.
We don't though, so take care to order your draw calls!
// Draw the cursor to the canvas
void Marker::draw(RenderContext& renderTarget) {
// Adjust marker by board spacing
// (This is kind of a hack and should be changed)
int tmpX, tmpY;
tmpX = ((m_xPos * 5) + 1);
tmpY = ((m_yPos * 3) + 1);
// Set surrounding elements
renderTarget.setContentAt(tmpX - 0, tmpY - 1, '-');
renderTarget.setContentAt(tmpX - 1, tmpY - 0, '|');
renderTarget.setContentAt(tmpX - 0, tmpY + 1, '-');
renderTarget.setContentAt(tmpX + 1, tmpY - 0, '|');
}
CmdPromptHelper
The last class that I'm going to talk about is the CmdPromptHelper. You don't have anything like this in your original question. However, you will need to worry about it soon. This class is also only useful on Windows so if you are on linux/unix, you will need to worry about dealing with drawing to the shell yourself.
class CmdPromptHelper {
private:
DWORD inMode; // Attributes of std::in before we change them
DWORD outMode; // Attributes of std::out before we change them
HANDLE hstdin; // Handle to std::in
HANDLE hstdout; // Handle to std::out
public:
CmdPromptHelper();
void reset();
WORD getKeyPress();
void clearScreen();
};
Each one of the functions is important. The constructor gets handles to the std::in and std::out of the current command prompt. The getKeyPress function returns what key the user presses down (key-up events are ignored). And the clearScreen function clears the prompt (not really, it actually moves whatever is already in the prompt up).
getKeyPress just makes sure you have a handle and then reads what has been typed into the console. It makes sure that whatever it is, it is a key and that it is being pressed down. Then it returns the key code as a Windows specific enum usually prefaced by VK_.
// See what key is pressed by the user and return it
WORD CmdPromptHelper::getKeyPress() {
if (hstdin != INVALID_HANDLE_VALUE) {
DWORD count;
INPUT_RECORD inrec;
// Get Key Press
ReadConsoleInput(hstdin, &inrec, 1, &count);
// Return key only if it is key down
if (inrec.Event.KeyEvent.bKeyDown) {
return inrec.Event.KeyEvent.wVirtualKeyCode;
} else {
return 0;
}
// Flush input
FlushConsoleInputBuffer(hstdin);
} else {
return 0;
}
}
clearScreen is a little deceiving. You would think that it clears out the text in the prompt. As far as I know, it doesn't. I'm pretty sure it actually shifts all the content up and then writes a ton of characters to the prompt to make it look like the screen was cleared.
An important concept that this function brings up though is the idea of buffered rendering. Again, if this were a more robust system, we would want to implement the concept of double buffering which means rendering to an invisible buffer and waiting until all drawing is finished and then swap the invisible buffer with the visible one. This makes for a much cleaner view of the render because we don't see things while they are still getting drawn. The way we do things here, we see the rendering process happen right in front of us. It's not a major concern, it just looks ugly sometimes.
// Flood the console with empty space so that we can
// simulate single buffering (I have no idea how to double buffer this)
void CmdPromptHelper::clearScreen() {
if (hstdout != INVALID_HANDLE_VALUE) {
CONSOLE_SCREEN_BUFFER_INFO csbi;
DWORD cellCount; // How many cells to paint
DWORD count; // How many we painted
COORD homeCoord = {0, 0}; // Where to put the cursor to clear
// Get console info
if (!GetConsoleScreenBufferInfo(hstdout, &csbi)) {
return;
}
// Get cell count
cellCount = csbi.dwSize.X * csbi.dwSize.Y;
// Fill the screen with spaces
FillConsoleOutputCharacter(
hstdout,
(TCHAR) ' ',
cellCount,
homeCoord,
&count
);
// Set cursor position
SetConsoleCursorPosition(hstdout, homeCoord);
}
}
main
The very last thing that you need to worry about is how to use all these things. That's where main comes in. You need a game loop. Game loops are probably the most important thing in any game. Any game that you look at will have a game loop.
The idea is:
Show something on screen
Read input
Handle the input
GOTO 1
This program is no different. The first thing it does is create a GameBoard and a RenderContext. It also makes a CmdPromptHelper which lets of interface with the command prompt. After that, it starts the loop and lets the loop continue until we hit the exit condition (for us that's pressing escape). We could have a separate class or function do dispatch input, but since we just dispatch the input to another input handler, I kept it in the main loop. After you get the input, you send if off to the GameBoard which alters itself accordingly. The next step is to clear the RenderContext and the screen/prompt. Then rerun the loop if escape wasn't pressed.
int main() {
WORD key;
GameBoard gb(5, 5);
RenderContext rc(25, 15);
CmdPromptHelper cph;
do {
gb.draw(rc);
rc.render();
key = cph.getKeyPress();
switch (key) {
case VK_UP:
gb.handleInput(MD_UP);
break;
case VK_DOWN:
gb.handleInput(MD_DOWN);
break;
case VK_LEFT:
gb.handleInput(MD_LEFT);
break;
case VK_RIGHT:
gb.handleInput(MD_RIGHT);
break;
}
rc.clear();
cph.clearScreen();
} while (key != VK_ESCAPE);
}
After you have taken into consideration all of these things, you understand why and where you need to be drawing your cursor. It's not a matter of calling a function after another, you need to composite your draws. You can't just draw the GameBoard and then draw the Marker. At least not with the command prompt. I hope this helps. It definitely alleviated the down time at work.

Resources