OpenGL using mouse for FPS Style movement - c

When i run my program and start moving mouse nothing really happens at all. I have wasd working fine but like mentioned am having problems with mouse movement.
I believe my issue is that it always resets to center but im not sure.
#define FPS 60
#define TO_RADIANS 3.14/180.0
float pitch = 0.0, yaw= 0.0;
float cX=0.0,cZ=0.0;
const int width = 16*50;
const int height = 9*50;
struct Motion
{
bool Forward,Backward,Left,Right;
}motion = {false,false,false,false};
void init()
{
glutSetCursor(GLUT_CURSOR_NONE);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glutWarpPointer(width/2,height/2);
}
void camera()
{
if(motion.Forward)
{
cX += cos((yaw+90)*TO_RADIANS)/5.0;
cZ -= sin((yaw+90)*TO_RADIANS)/5.0;
}
if(motion.Backward)
{
cX += cos((yaw+90+180)*TO_RADIANS)/5.0;
cZ -= sin((yaw+90+180)*TO_RADIANS)/5.0;
}
if(motion.Left)
{
cX += cos((yaw+90+90)*TO_RADIANS)/5.0;
cZ -= sin((yaw+90+90)*TO_RADIANS)/5.0;
}
if(motion.Right)
{
cX += cos((yaw+90-90)*TO_RADIANS)/5.0;
cZ -= sin((yaw+90-90)*TO_RADIANS)/5.0;
}
/*limit the values of pitch
between -60 and 70
*/
if(pitch>=70)
pitch = 70;
if(pitch<=-60)
pitch=-60;
glRotatef(-pitch,1.0,0.0,0.0); // Along X axis
glRotatef(-yaw,0.0,1.0,0.0); //Along Y axis
glTranslatef(-cX,0.0,-cZ);
}
void timer()
{
glutPostRedisplay();
glutWarpPointer(width/2,height/2);
glutTimerFunc(1000/FPS,timer,0);
}
void keyboard(unsigned char key,int x,int y)
{
switch(key)
{
case 'W':
case 'w':
motion.Forward = true;
break;
case 'A':
case 'a':
motion.Left = true;
break;
case 'S':
case 's':
motion.Backward = true;
break;
case 'D':
case 'd':
motion.Right = true;
break;
}
}
void keyboard_up(unsigned char key,int x,int y)
{
switch(key)
{
case 'W':
case 'w':
motion.Forward = false;
break;
case 'A':
case 'a':
motion.Left = false;
break;
case 'S':
case 's':
motion.Backward = false;
break;
case 'D':
case 'd':
motion.Right = false;
break;
}
}
int main(int argc,char**argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(width, height);
glutCreateWindow("Jameson Marzak FPS");
glutFullScreen();
sky[0] = LoadTexBMP("sky0.bmp");
sky[1] = LoadTexBMP("sky1.bmp");
sky[2] = LoadTexBMP("grass.bmp");
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
//glutPassiveMotionFunc(passive_motion);
glutTimerFunc(0,timer,0); //more info about this is given below at definition of timer()
glutKeyboardFunc(keyboard);
glutKeyboardUpFunc(keyboard_up);
glutMainLoop();
return 0;
}

You need to set up a callback with glut to handle mouse inputs:
glutMouseFunc
then, figure out how to calculate the proper yaw/pitch from the mouse x and mouse y that glut will call your callback with

Related

How can I run Raspberry pi's sample code on Code Blocks

I am working on a sample code of Raspberry PI 3(file path is: /opt/vc/src/hello_pi/hello_tiger). I want to run this sample code on Code Blocks. I created new project on Code Blocks and added main.c file and header file. I compiled this code, and I got an error. This was the error:
'rotaten' undeclared(first use in this function).
If I run the code on LXTerminal using the ./hello_tiger.bin command it works fine. But I want to run this code on Code Blocks or any compiler(such as monodevelop). The main.c file is given below.
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <assert.h>
#include <string.h>
#define UNREF(X) ((void)(X))
//#ifdef HG_FLAT_INCLUDES
#include "/opt/vc/src/hello_pi/libs/vgfont/VG/openvg.h"
#include "/opt/vc/src/hello_pi/libs/vgfont/VG/vgu.h"
#include "/opt/vc/src/hello_pi/libs/vgfont/EGL/egl.h"
/*
# include "openvg.h"
# include "vgu.h"
# include "egl.h" */
/*/#else
# include "VG/openvg.h"
# include "VG/vgu.h"
# include "EGL/egl.h"
#endif
*/
#include "tiger.h"
/*--------------------------------------------------------------*/
#ifdef __RASPBERRYPI__
static float rotateN = 0.0f;
#endif
const float aspectRatio = 612.0f / 792.0f;
int renderWidth = 0;
int renderHeight = 0;
EGLDisplay egldisplay;
EGLConfig eglconfig;
EGLSurface eglsurface;
EGLContext eglcontext;
/*--------------------------------------------------------------*/
typedef struct
{
VGFillRule m_fillRule;
VGPaintMode m_paintMode;
VGCapStyle m_capStyle;
VGJoinStyle m_joinStyle;
float m_miterLimit;
float m_strokeWidth;
VGPaint m_fillPaint;
VGPaint m_strokePaint;
VGPath m_path;
} PathData;
typedef struct
{
PathData* m_paths;
int m_numPaths;
} PS;
PS* PS_construct(const char* commands, int commandCount, const float* points, int pointCount)
{
PS* ps = (PS*)malloc(sizeof(PS));
int p = 0;
int c = 0;
int i = 0;
int paths = 0;
int maxElements = 0;
unsigned char* cmd;
UNREF(pointCount);
while(c < commandCount)
{
int elements, e;
c += 4;
p += 8;
elements = (int)points[p++];
assert(elements > 0);
if(elements > maxElements)
maxElements = elements;
for(e=0;e<elements;e++)
{
switch(commands[c])
{
case 'M': p += 2; break;
case 'L': p += 2; break;
case 'C': p += 6; break;
case 'E': break;
default:
assert(0); //unknown command
}
c++;
}
paths++;
}
ps->m_numPaths = paths;
ps->m_paths = (PathData*)malloc(paths * sizeof(PathData));
cmd = (unsigned char*)malloc(maxElements);
i = 0;
p = 0;
c = 0;
while(c < commandCount)
{
int elements, startp, e;
float color[4];
//fill type
int paintMode = 0;
ps->m_paths[i].m_fillRule = VG_NON_ZERO;
switch( commands[c] )
{
case 'N':
break;
case 'F':
ps->m_paths[i].m_fillRule = VG_NON_ZERO;
paintMode |= VG_FILL_PATH;
break;
case 'E':
ps->m_paths[i].m_fillRule = VG_EVEN_ODD;
paintMode |= VG_FILL_PATH;
break;
default:
assert(0); //unknown command
}
c++;
//stroke
switch( commands[c] )
{
case 'N':
break;
case 'S':
paintMode |= VG_STROKE_PATH;
break;
default:
assert(0); //unknown command
}
ps->m_paths[i].m_paintMode = (VGPaintMode)paintMode;
c++;
//line cap
switch( commands[c] )
{
case 'B':
ps->m_paths[i].m_capStyle = VG_CAP_BUTT;
break;
case 'R':
ps->m_paths[i].m_capStyle = VG_CAP_ROUND;
break;
case 'S':
ps->m_paths[i].m_capStyle = VG_CAP_SQUARE;
break;
default:
assert(0); //unknown command
}
c++;
//line join
switch( commands[c] )
{
case 'M':
ps->m_paths[i].m_joinStyle = VG_JOIN_MITER;
break;
case 'R':
ps->m_paths[i].m_joinStyle = VG_JOIN_ROUND;
break;
case 'B':
ps->m_paths[i].m_joinStyle = VG_JOIN_BEVEL;
break;
default:
assert(0); //unknown command
}
c++;
//the rest of stroke attributes
ps->m_paths[i].m_miterLimit = points[p++];
ps->m_paths[i].m_strokeWidth = points[p++];
//paints
color[0] = points[p++];
color[1] = points[p++];
color[2] = points[p++];
color[3] = 1.0f;
ps->m_paths[i].m_strokePaint = vgCreatePaint();
vgSetParameteri(ps->m_paths[i].m_strokePaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
vgSetParameterfv(ps->m_paths[i].m_strokePaint, VG_PAINT_COLOR, 4, color);
color[0] = points[p++];
color[1] = points[p++];
color[2] = points[p++];
color[3] = 1.0f;
ps->m_paths[i].m_fillPaint = vgCreatePaint();
vgSetParameteri(ps->m_paths[i].m_fillPaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
vgSetParameterfv(ps->m_paths[i].m_fillPaint, VG_PAINT_COLOR, 4, color);
//read number of elements
elements = (int)points[p++];
assert(elements > 0);
startp = p;
for(e=0;e<elements;e++)
{
switch( commands[c] )
{
case 'M':
cmd[e] = VG_MOVE_TO | VG_ABSOLUTE;
p += 2;
break;
case 'L':
cmd[e] = VG_LINE_TO | VG_ABSOLUTE;
p += 2;
break;
case 'C':
cmd[e] = VG_CUBIC_TO | VG_ABSOLUTE;
p += 6;
break;
case 'E':
cmd[e] = VG_CLOSE_PATH;
break;
default:
assert(0); //unknown command
}
c++;
}
ps->m_paths[i].m_path = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1.0f, 0.0f, 0, 0, (unsigned int)VG_PATH_CAPABILITY_ALL);
vgAppendPathData(ps->m_paths[i].m_path, elements, cmd, points + startp);
i++;
}
free(cmd);
return ps;
}
void PS_destruct(PS* ps)
{
int i;
assert(ps);
for(i=0;i<ps->m_numPaths;i++)
{
vgDestroyPaint(ps->m_paths[i].m_fillPaint);
vgDestroyPaint(ps->m_paths[i].m_strokePaint);
vgDestroyPath(ps->m_paths[i].m_path);
}
free(ps->m_paths);
free(ps);
}
void PS_render(PS* ps)
{
int i;
assert(ps);
vgSeti(VG_BLEND_MODE, VG_BLEND_SRC_OVER);
for(i=0;i<ps->m_numPaths;i++)
{
vgSeti(VG_FILL_RULE, ps->m_paths[i].m_fillRule);
vgSetPaint(ps->m_paths[i].m_fillPaint, VG_FILL_PATH);
if(ps->m_paths[i].m_paintMode & VG_STROKE_PATH)
{
vgSetf(VG_STROKE_LINE_WIDTH, ps->m_paths[i].m_strokeWidth);
vgSeti(VG_STROKE_CAP_STYLE, ps->m_paths[i].m_capStyle);
vgSeti(VG_STROKE_JOIN_STYLE, ps->m_paths[i].m_joinStyle);
vgSetf(VG_STROKE_MITER_LIMIT, ps->m_paths[i].m_miterLimit);
vgSetPaint(ps->m_paths[i].m_strokePaint, VG_STROKE_PATH);
}
vgDrawPath(ps->m_paths[i].m_path, ps->m_paths[i].m_paintMode);
}
assert(vgGetError() == VG_NO_ERROR);
}
PS* tiger = NULL;
/*--------------------------------------------------------------*/
void render(int w, int h)
{
#ifndef __RASPBERRYPI__
if(renderWidth != w || renderHeight != h)
#endif
{
float clearColor[4] = {0,0,0,0};
float scale = w / (tigerMaxX - tigerMinX);
eglSwapBuffers(egldisplay, eglsurface); //force EGL to recognize resize
vgSetfv(VG_CLEAR_COLOR, 4, clearColor);
vgClear(0, 0, w, h);
vgLoadIdentity();
#ifdef __RASPBERRYPI__
vgTranslate(w * 0.5f, h * 0.5f);
vgRotate(rotateN);
vgTranslate(-w * 0.5f, -h * 0.5f);
#endif
vgScale(scale, scale);
vgTranslate(-tigerMinX, -tigerMinY + 0.5f * (h / scale - (tigerMaxY - tigerMinY)));
PS_render(tiger);
assert(vgGetError() == VG_NO_ERROR);
renderWidth = w;
renderHeight = h;
}
#ifndef __RASPBERRYPI__
eglSwapBuffers(egldisplay, eglsurface);
assert(eglGetError() == EGL_SUCCESS);
#endif
}
/*--------------------------------------------------------------*/
void init(NativeWindowType window)
{
static const EGLint s_configAttribs[] =
{
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_LUMINANCE_SIZE, EGL_DONT_CARE, //EGL_DONT_CARE
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_SAMPLES, 1,
EGL_NONE
};
EGLint numconfigs;
egldisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglInitialize(egldisplay, NULL, NULL);
assert(eglGetError() == EGL_SUCCESS);
eglBindAPI(EGL_OPENVG_API);
eglChooseConfig(egldisplay, s_configAttribs, &eglconfig, 1, &numconfigs);
assert(eglGetError() == EGL_SUCCESS);
assert(numconfigs == 1);
eglsurface = eglCreateWindowSurface(egldisplay, eglconfig, window, NULL);
assert(eglGetError() == EGL_SUCCESS);
eglcontext = eglCreateContext(egldisplay, eglconfig, NULL, NULL);
assert(eglGetError() == EGL_SUCCESS);
eglMakeCurrent(egldisplay, eglsurface, eglsurface, eglcontext);
assert(eglGetError() == EGL_SUCCESS);
tiger = PS_construct(tigerCommands, tigerCommandCount, tigerPoints, tigerPointCount);
}
/*--------------------------------------------------------------*/
void deinit(void)
{
PS_destruct(tiger);
eglMakeCurrent(egldisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
assert(eglGetError() == EGL_SUCCESS);
eglTerminate(egldisplay);
assert(eglGetError() == EGL_SUCCESS);
eglReleaseThread();
}
#include "/opt/vc/src/hello_pi/libs/vgfont/bcm_host.h"
int main(void)
{
uint32_t width, height;
bcm_host_init();
int s;
static EGL_DISPMANX_WINDOW_T nativewindow;
DISPMANX_ELEMENT_HANDLE_T dispman_element;
DISPMANX_DISPLAY_HANDLE_T dispman_display;
DISPMANX_UPDATE_HANDLE_T dispman_update;
VC_RECT_T dst_rect;
VC_RECT_T src_rect;
s = graphics_get_display_size(0 /* LCD */, &width, &height);
assert( s >= 0 );
dst_rect.x = 0;
dst_rect.y = 0;
dst_rect.width = width;
dst_rect.height = height;
src_rect.x = 0;
src_rect.y = 0;
src_rect.width = width << 16;
src_rect.height = height << 16;
dispman_display = vc_dispmanx_display_open( 0 /* LCD */);
dispman_update = vc_dispmanx_update_start( 0 );
dispman_element = vc_dispmanx_element_add ( dispman_update, dispman_display,
1/*layer*/, &dst_rect, 0/*src*/,
&src_rect, DISPMANX_PROTECTION_NONE, 0 /*alpha*/, 0/*clamp*/, 0/*transform*/);
nativewindow.element = dispman_element;
nativewindow.width = width;
nativewindow.height = height;
vc_dispmanx_update_submit_sync( dispman_update );
init(&nativewindow);
while (1) {
render(width, height);
rotateN += 1.0f; // compiler remarks this line
}
deinit();
return 0;
}
Compiler displays the remark at the bottom:
The definition of rotateN is visible to the compiler only if the macro __RASPBERRYPI__ is defined. As it is not defined in the code or any of the included header files or compiler options, you have this error.

Creating a FIFO Queue with Keypad Inputs

I'm trying to implement a FIFO queue for keypad inputs but cannot seem to get it to work. I'm able to get the keypad inputs to appear on an LCD screen but that is all I'm able to do. I think the code is supposed to read a keypad input and push it into a queue, then pop the keypad input and read the value onto an LCD screen. Could anyone advise on why it doesn't display all the values I've pressed? Thank you.
#include "project.h"
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
// Keypad Variables
char KeyPad[4][4] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'},
};
char ReadKeyPad();
// FIFO Variables
struct FIFO {
char key;
struct FIFO *next;
};
struct FIFO KeyQueue[] = {
{0, &KeyQueue[1]}, //[0]
{0, &KeyQueue[2]}, //[1]
{0, &KeyQueue[3]}, //[2]
{0, &KeyQueue[4]}, //[3]
{0, &KeyQueue[5]}, //[4]
{0, &KeyQueue[6]}, //[5]
{0, &KeyQueue[7]}, //[6]
{0, &KeyQueue[8]}, //[7]
{0, &KeyQueue[0]} //[8]
};
struct FIFO *Head;
struct FIFO *Tail;
int KeyQueue_Size=0;
bool KeyQueue_IsEmpty();
bool KeyQueue_IsFull();
void KeyQueue_Push(char key);
char KeyQueue_Pop();
char ReadKeyPad();
int delay = 10;
int main(void)
{
Head = Tail = &KeyQueue[0];
char key;
CyGlobalIntEnable; /* Enable global interrupts. */
/* Place your initialization/startup code here (e.g. MyInst_Start()) */
LCD_Start();
LCD_ClearDisplay();
LCD_Enable();
for(;;)
{
/* Place your application code here. */
key = ReadKeyPad();
LCD_Position(1,8);
LCD_PutChar(key);
if (key !=0)
{
if (!KeyQueue_IsFull())
KeyQueue_Push(key);
}
//task for poping key
delay --;
if(delay <= 0 && !KeyQueue_IsEmpty())
{
KeyQueue_Pop();
switch (key)
{
case '1':
LCD_Position(0,1);
LCD_PrintString("You pressed 1");
break;
case '2':
LCD_Position(0,1);
LCD_PrintString("You pressed 2");
break;
case '3':
LCD_Position(0,1);
LCD_PrintString("You pressed 3");
break;
case '4':
LCD_Position(0,1);
LCD_PrintString("You pressed 4");
break;
case '5':
LCD_Position(0,1);
LCD_PrintString("You pressed 5");
break;
case '6':
LCD_Position(0,1);
LCD_PrintString("You pressed 6");
break;
case '7':
LCD_Position(0,1);
LCD_PrintString("You pressed 7");
break;
case '8':
LCD_Position(0,1);
LCD_PrintString("You pressed 8");
break;
case '9':
LCD_Position(0,1);
LCD_PrintString("You pressed 9");
break;
case 'A':
LCD_Position(0,1);
LCD_PrintString("You pressed A");
break;
case 'B':
LCD_Position(0,1);
LCD_PrintString("You pressed B");
break;
case 'C':
LCD_Position(0,1);
LCD_PrintString("You pressed C");
break;
case 'D':
LCD_Position(0,1);
LCD_PrintString("You pressed D");
break;
case '*':
LCD_Position(0,1);
LCD_PrintString("You pressed *");
break;
case '#':
LCD_Position(0,1);
LCD_PrintString("You pressed #");
break;
case '0':
LCD_Position(0,1);
LCD_PrintString("You pressed 0");
break;
delay = 10;
}
CyDelayUs(100);
}
}
}
bool KeyQueue_IsEmpty()
{
if(KeyQueue_Size == 0) return true;
return false;
}
bool KeyQueue_IsFull()
{
//if (Head == Tail) return truel
if(KeyQueue_Size ==9) return true;
return false;
}
void KeyQueue_Push(char key)
{
Head->key=key;
Head = Head->next;
KeyQueue_Size ++;
}
char KeyQueue_Pop()
{
char key;
key = Tail->key;
Tail = Tail->next;
KeyQueue_Size --;
return key;
}
char ReadKeyPad()
{
int i;
char key;
uint8_t col;
for (i=0; i<4; i++)
{
key = 0;
ROW_Write(1<<i);
col=COL_Read();
//LCD_Position(1,0);
//LCD_PrintNumber(key);
if (col & 0x01) key=KeyPad[i][0];
if (col & 0x02) key=KeyPad[i][1];
if (col & 0x04) key=KeyPad[i][2];
if (col & 0x08) key=KeyPad[i][3];
if (key != 0) break;
}
return key;
}
Some problems in your code:
As pointed before, delay = 10; is not well placed
key variable of main function is set only at the beginning of for loop.
So a corrected code could be:
for(;;)
{
key = ReadKeyPad();
LCD_Position(1,8);
LCD_PutChar(key);
if (key !=0)
{
if (!KeyQueue_IsFull())
KeyQueue_Push(key);
}
//task for poping key
delay --;
if(delay <= 0 && !KeyQueue_IsEmpty())
{
/* don't forget to store what have been poped from fifo */
key = KeyQueue_Pop();
switch (key)
{
case '1':
LCD_Position(0,1);
LCD_PrintString("You pressed 1");
delay = 10;
break;
case '2':
LCD_Position(0,1);
LCD_PrintString("You pressed 2");
delay = 10;
break;
/*
.
.
.
*/
case '0':
LCD_Position(0,1);
LCD_PrintString("You pressed 0");
delay = 10;
break;
}
CyDelayUs(100);
}
}
Maybe you can write it shorter:
for(;;)
{
key = ReadKeyPad();
LCD_Position(1,8);
LCD_PutChar(key);
if (key !=0)
{
if (!KeyQueue_IsFull())
KeyQueue_Push(key);
}
//task for poping key
delay --;
if(delay <= 0 && !KeyQueue_IsEmpty())
{
/* don't forget to store what have been poped from fifo */
key = KeyQueue_Pop();
/* print what have been pressed */
LCD_Position(0,1);
LCD_PrintString("You pressed ");
LCD_Position(0,12);
LCD_PutChar(key);
delay = 10;
CyDelayUs(100);
}
}

Escape delay with a button in a game

I have a problem with a piece of code for a game. I would like to know, how to break the time delay if I press the button.
List of files
At the end, the game writes your end score on the LCD for 10 seconds. And goes back to the wait for start. I want to keep that as it is - the only thing that I want to include is that if I press the button within those 10 seconds I want it to go immediately back to the wait for start.
Function code is here
void DrawGameScore()
{ //&RFONT_8X12 &RFONT_16X26
//char key;
//key = KBD_GetKey();
char txt[10];
UG_FontSelect(&RFONT_16X26);
UG_SetForecolor(C_WHITE);
switch (level){
case 1:
UG_PutString(60,130,"Peasant Score:");
sprintf(txt,"%d",score);
UG_PutString(120,160,txt);
_delay_ms(10000);
break;
case 2:
UG_PutString(60,130,"Knight Score:");
sprintf(txt,"%d",score);
UG_PutString(120,160,txt);
_delay_ms(10000);
break;
case 3:
UG_PutString(60,130,"Queen Score:");
sprintf(txt,"%d",score);
UG_PutString(120,160,txt);
_delay_ms(10000);
break;
case 4:
UG_PutString(60,130,"King Score:");
sprintf(txt,"%d",score);
UG_PutString(120,160,txt);
_delay_ms(10000);
break;
case 5:
UG_PutString(60,130,"God Score:");
sprintf(txt,"%d",score);
UG_PutString(120,160,txt);
_delay_ms(10000);
break;
}
//UG_PutString(60,130,"Final Score:");
//sprintf(txt,"%d",score);
//UG_PutString(120,160,txt);
//_delay_ms(1000);
}
When the game is over this function draws your score based on your level. In this next function i am calling drawgamescore function, which is in dsip_end_score makro.
int EndOfGame()
{
char key;
//static int state;
int result = 1;
key = KBD_GetKey();
display_msg = DSIP_END_SCORE;
if (key == BTN_OK){
//display_msg = DISP_REFRESH_ALL;
//display_msg = DSIP_END_SCORE;
return result;
}
return result;
}
Here is the main game function
void Game()
{
static int state;
int result;
switch (state)
{
case 1: //waiting for the game start
result = WaitForStart();
if (result == 1) state++;
break;
case 2: //Play the game
result = PlayTheGame();
if (result == 1) state++;
break;
case 3: //Display the score
result = EndOfGame();
if (result == 1) state=0;
break;
default: //0 or unknown value: reset the game
state = 1;
break;
}
}
Thanks.
I tried
int EndOfGame()
{
char key;
static int state;
int result = 1;
key = KBD_GetKey();
display_msg = DSIP_END_SCORE;
if (key == BTN_OK){
//display_msg = DISP_REFRESH_ALL;
//display_msg = DSIP_END_SCORE;
return result;
}
return result;
}
/*
display_msg = DSIP_END_SCORE;
if (key != 0){
switch (key)
{
case BTN_OK:
return result;
break;
}
}
*/
/*
switch (state)
{
case 0:
display_msg = DSIP_END_SCORE;
state++;
break;
case 1:
key = KBD_GetKey();
if (key != 0){
switch (key)
{
case BTN_OK:
return result;
break;
}
break;
}
}
return result;
*/
//display_msg = DISP_REFRESH_ALL;
//display_msg = DSIP_END_SCORE;
//return result;
/*
char key;
int result=0;
//static int state;
key = KBD_GetKey();
if (KBD_isKeyStatePressed(BTN_OK))
{
display_msg = DSIP_END_SCORE;
result = 1;
} else {
result = 1;
}
//return result;
*/
/*
switch (state){
case 0:
KBD_flush(); //empty buffer
//display_msg = DISP_REFRESH_ALL;
display_msg = DSIP_END_SCORE;
return result;
state++;
break;
case 1:
key = KBD_GetKey(); //kbd read dela background services
if (key == BTN_OK){
//display_msg = DISP_REFRESH_ALL;
display_msg = DSIP_END_SCORE;
return result;
break;
}
break;
}
return result;
*/
/*
key = KBD_GetKey();
if (key == BTN_OK) {
//display_msg = DISP_REFRESH_ALL;
return result;
}else{
display_msg = DISP_REFRESH_ALL;
display_msg = DSIP_END_SCORE;
//TODO: write the program
return result;
}*/
I found a solution!
Here is the code if anyone is interested.
int EndOfGame()
{
int result = 0;
char key;
static uint32_t timeStamp;
static int state = 0;
display_msg = DISP_REFRESH_ALL;
switch (state)
{
case 0: //Show end score
display_msg = DSIP_END_SCORE;
timeStamp = GetSysTick();
state++;
break;
case 1: //read keys after 2 seconds
if (Has_X_MillisecondsPassed(2000, &timeStamp)
{
state++;
KBD_flush();
break;
}
break;
case 2:
key = KBD_GetKey();
if (key != 0)
{
switch (key)
{
case BTN_OK:
state = 0;
result = 1;
break;
}
}
//finish after 10 seconds
if (Has_X_MillisecondsPassed(10000, &timeStamp))
{
result = 1;
state = 0;
break;
}
break;
}
return result;
}
If you want to know about the
Has_X_millisecondsPassed();
function you are welcome to see it in systime.c in the File list hyperlink in the question above. For the reference i'm using AtMega328pb microcontroller.

Tic Tac Toe - Turns C

I've been turning around and around trying to figure out how to give my players turns. The questions is for there to be two players playing tic tac toe but I can't figure how to do that. Here's my code:
#include <stdio.h>
#include <stdlib.h>
void displayBoard(char [3][3]);enter code here
int playerType (int player, char boardArray[3][3]);
int selectLocation(char [3][3], int , int );
char setTurn(char [3][3], int , int , char );
int main()
{
int player,location;
char position;
char boardArray[3][3]={{'1','2','3'},
{'4','5','6'},
{'7','8','9'}};
player= playerType (player, boardArray);
int i;
for(i=0;i<9;i++)
{
if (player==3)
break;
else{
location=selectLocation(boardArray, player, location);
position=setTurn(boardArray, location, player, position);
}
}
return 0;
}
void displayBoard(char boardArray [3][3]) //This displays the tic tac toe board
{
printf("\t%c|%c|%c\n", boardArray[0][0], boardArray[0][1], boardArray[0][2]);
printf("\t%c|%c|%c\n", boardArray[1][0], boardArray[1][1], boardArray[1][2]);
printf("\t%c|%c|%c\n", boardArray[2][0], boardArray[2][1], boardArray[2][2]);
}
int playerType (int player, char boardArray [3][3]) //This decides who plays first
{
player=0;
printf("Enter 1 for Player X.\n");
printf("Enter 2 for Player O.\n");
printf("Enter 3 to Quit. \n");
scanf("%d", &player);
if (player == 1)
{
printf("You're player X.\n");
displayBoard(boardArray);
}
else if (player == 2)
{
printf("You're player O.\n");
displayBoard(boardArray);
}
else if(player == 3)
printf("You Quit.\n");
else
printf("Invalid Entry.\n");
return player;
}
int selectLocation(char boardArray[3][3], int player, int location) //This takes in the location
{
printf("Pick a location from 1-9.\n");
scanf("%d", &location);
return location;
}
char setTurn(char boardArray[3][3], int location, int player, char position) //This outputs the location
{
if (player == 1)
{
switch(location)
{
case 1:
{
boardArray[0][0]='x';
break;
}
case 2:
{
boardArray[0][1]='x';
break;
}
case 3:
{
boardArray[0][2]='x';
break;
}
case 4:
{
boardArray[1][0]='x';
break;
}
case 5:
{
boardArray[1][1]='x';
break;
}
case 6:
{
boardArray[1][2]='x';
break;
}
case 7:
{
boardArray[2][0]='x';
break;
}
case 8:
{
boardArray[2][1]='x';
break;
}
case 9:
{
boardArray[2][2]='x';
break;
}
default:
printf("invalid");
}
}
else if (player == 2)
{
switch(location)
{
case 1:
{
boardArray[0][0]='O';
break;
}
case 2:
{
boardArray[0][1]='O';
break;
}
case 3:
{
boardArray[0][2]='O';
break;
}
case 4:
{
boardArray[1][0]='O';
break;
}
case 5:
{
boardArray[1][1]='O';
break;
}
case 6:
{
boardArray[1][2]='O';
break;
}
case 7:
{
boardArray[2][0]='O';
break;
}
case 8:
{
boardArray[2][1]='O';
break;
}
case 9:
{
boardArray[2][2]='O';
break;
}
default:
printf("Invalid");
}
}
printf("\t%c|%c|%c\n", boardArray[0][0], boardArray[0][1], boardArray[0][2]);
printf("\t%c|%c|%c\n", boardArray[1][0], boardArray[1][1], boardArray[1][2]);
printf("\t%c|%c|%c\n", boardArray[2][0], boardArray[2][1], boardArray[2][2]);
return position;
}
Change player selection part player= playerType (player, boardArray); inside for loop like this -
int player,location;
char position;
char boardArray[3][3]={{'1','2','3'},
{'4','5','6'},
{'7','8','9'}};
int i;
for(i=0;i<9;i++)
{
player= playerType (player, boardArray);
if (player==3)
break;
else
{
location=selectLocation(boardArray, player, location);
position=setTurn(boardArray, location, player, position);
}
}

C SDL Keyboard Events SDL_KEYUP Triggering When Key Is Down

I am using SDL in C, and I'm trying to make a character move on the screen when a key is pressed, and stop when it is released, but it seems as if the KEYUP event is triggering when the key is still being held down. If I remove the KEYUP section in pressed(), the characters will slide across the screen, but obviously won't stop on their own. If I leave the KEYUP section in, I have to press the key repeatedly to move them across the screen.
Any idea what I'm doing wrong?
Here's what I have:
...
int done = 0;
while (done==0)
{
pressed();
if (kenter == 1)
{
state = 1;
subscreen();
}
if (kescape == 1)
{
done = 1;
}
if (kup == 1)
{
playery += -2;
}
if (kdown == 1)
{
playery += 2;
}
if (kright == 1)
{
playerx += 2;
}
if (kleft == 1)
{
playerx += - 2;
}
...
int pressed ()
{
SDL_Event keyevent;
while (SDL_PollEvent(&keyevent))
{
switch(keyevent.type)
{
case SDL_KEYDOWN:
switch(keyevent.key.keysym.sym)
{
case SDLK_RETURN:
{
kenter = 1;
break;
}
case SDLK_ESCAPE:
{
kescape = 1;
break;
}
case SDLK_a:
{
ka = 1;
break;
}
case SDLK_s:
{
ks = 1;
break;
}
case SDLK_UP:
{
kup = 1;
break;
}
case SDLK_DOWN:
{
kdown = 1;
break;
}
case SDLK_RIGHT:
{
kright = 1;
break;
}
case SDLK_LEFT:
{
kleft = 1;
break;
}
default:
break;
}
}
switch(keyevent.type)
{
case SDL_KEYUP:
switch(keyevent.key.keysym.sym)
{
case SDLK_RETURN:
{
kenter = 0;
break;
}
case SDLK_ESCAPE:
{
kescape = 0;
break;
}
case SDLK_a:
{
ka = 0;
break;
}
case SDLK_s:
{
ks = 0;
break;
}
case SDLK_UP:
{
kup = 0;
break;
}
case SDLK_DOWN:
{
kdown = 0;
break;
}
case SDLK_RIGHT:
{
kright = 0;
break;
}
case SDLK_LEFT:
{
kleft = 0;
break;
}
default:
break;
}
}
}
return 0;
}
I think your switch statements are broken.
Use this less confusing way
int pressed ()
{
SDL_Event event;
while(SDL_PollEvent(&event) )
{
if(event.type == SDLK_KEYDOWN)
{
switch(event.key.keysym.sym)
{
case SDLK_RETURN:
doStuff = 1
break;
default:
break;
}
}
if(event.type == SDLK_KEYUP)
{
switch(event.key.keysym.sym)
{
case SDLK_RETURN:
doStuff = 0;
break;
default:
break;
}
}
}
}
Also important:
SDL Tutorials: Practical Keyboard Input
Oh and avoid using global variables!
Your use of two switch statements is odd and confusing, you should probably fix that.
The issues you're seeing are likely due to keyboard repeat, see the SDL_EnableKeyRepeat() call for how to disable it.
don't use switch. I experienced same thing, but I resolved into using 'if' like this. Maybe switch has 'else if'.
if(event.type == SDL_KEYDOWN){
....
}
if(event.type == SDL_KEYUP){
....
}

Resources