We're trying to make a project using atmega 16 and C language. The problem is that whenever we want to move a cursor, it goes to random places instead of moving one character right/left.
Our first idea was just
LCD_command(0x10);
for going left. It didn't work although we are sure it should (turning off the cursor works in the same function). We also tried:
uint8_t position = 0;
[...]
void whichButton(){
whatsPressed = keybord();
switch (whatsPressed):
case 1:
{
position = position + 1;
GoToXY (position, 0);
}
case 2:
{
position = position - 1;
GoToXY (position, 0); //for going left
}
}
Has anybody got any idea how to move it?
Related
I am working on a little sokoban game, using the SDL 1.2 library. The most interesting possibility of this program is to move a character on a map. However, I am facing some strange slowing-down problem which I fail to find the reason of.
I simplified the code so it is not too long.
Here is the loop that makes the character move:
The followings correspond to the blocks of the game (each case of the map) and its position on the screen. For example, bloc[3] is a pointer to the surface corresponding to the 4th case of the map.
SDL_Surface *bloc[256] = {NULL};
SDL_Rect pos_bloc[256];
while (on == 1)
{
SDL_WaitEvent(&event);
switch (event.type)
{
case SDL_KEYDOWN:
switch(event.key.keysym.sym)
{
case SDLK_ESCAPE:
on = game_menu(screen);
refresh_screen(screen, bloc, pos_bloc, zone);
break;
case SDLK_UP:
if (zone[m - 16] == ' ') // m is the position of the character on
// the map. As the map is 16 blocks large,
// and the position in the map is registered
// in a string, m - 16 means: 1 case up.
// m + 16 means: 1 case down.
m = swap_2blocs(screen, bloc, pos_bloc, zone, m, -16, "up.bmp");
break;
case SDLK_DOWN:
if (zone[m + 16] == ' ')
m = swap_2blocs(screen, bloc, pos_bloc, zone, m, 16, "down.bmp");
break;
default:;
}
default:;
}
SDL_Flip(screen);
}
Whenever the keys up or down are pressed, it calls a function that swap 2 surfaces: it frees both SDL_Surface pointers concerned and then reallocates some memory for another surface:
int swap_2blocs(SDL_Surface *screen, SDL_Surface *bloc[256], SDL_Rect pos_bloc[256], char zone[257], int m, int n, char *character)
{
SDL_FreeSurface(bloc[m]); // The surface pointed to by `bloc[m]` is freed
bloc[m] = SDL_LoadBMP("empty_space.bmp"); // `bloc[m]` now points to another surface
SDL_BlitSurface(bloc[m], NULL, screen, &pos_bloc[m]);
zone[m] = ' '; // zone is the string that contains informations about each map block
// ' ' stands for an empty space, 'M' stands for the character
m += n;
zone[m] = 'M';
SDL_FreeSurface(bloc[m]); // The surface pointed to by `bloc[m]` is freed
bloc[m] = SDL_LoadBMP(character); // `bloc[m]` now points to another surface
SDL_BlitSurface(bloc[m], NULL, screen, &pos_bloc[m]);
return m;
}
There are several things to be known:
The problem randomly appears 1 out of 3 times.
After 15-25 events (key up or key down), the slowing-down effect begins to be felt. After something like 30 events, it starts being really slow (there are around 300ms between the moment when the key is pressed, and the moment when the characters move on the screen).
It does slow down more than these approximative 300ms.
When the problem appears, going back to the main menu (which implies to free all the surfaces pointed to by each pointer contained in bloc) and starting a new game doesn't reset the speed of the game. To reset it, the program must be exited and then launched again.
I would like to understand this mysterious behaviour: where does it come from? What is happening?
I am trying to write the code for an embedded board (RX63N)in which I want to use the LCD along with the on board switches for the following functionality:
On pressing the switch the program should "pause" or "unpause" depending on the previous state and the LCD should display "paused" when it is paused. On unpausing, the LCD should display the custom graphics at the position defined by x and y. It is displayed using the function Set_LCD_Char(N) where N is defined as a custom graphic from a bitmap image. But I will need to clear the LCD before making any changes and that is where I am struggling. On using lcd_clear() function anywhere in the while keeps the LCD blank (or almost blank i.e. the text and graphics are so faint that they are as good as absent) Can someone please help me? heres the code:
while (1)
{
// lcd_clear();
if(g_sw3_press == true){ //detect switch press
pause_flag = !pause_flag;
g_sw3_press = false; //reset switch
}
if (pause_flag){
RESET_ALL_LEDS();
jet_x = 0;
jet_y = 0;
Set_Font_Bitmap(); //changes from text mode to bitmap
Set_LCD_Pos(jet_x,jet_y);
Set_LCD_Char(3);
}
else if(!(pause_flag)){
ALL_RED_LEDS_ON();
Set_Font_8_by_8();
lcd_display(LCD_LINE1, " PAUSED ");
}
}
Firstly, it's generally not a good idea to do a busy polling loop as you are doing. But I can't recommend any concrete alternatives as platform and OS (if any) have not been provided (perhaps your platform has no support for events).
Anyway, not sure if this is the answer you need. But since you ask for an example and I can't effectively put code into the comments, below is what I mean. The problem is that you are continuously writing and clearing the LCD. So in effect the two operations are competing with each other. So one way to solve this is to only update the LCD when the state changes.
while (1)
{
if(g_sw3_press == true){ //detect switch press
pause_flag = !pause_flag;
g_sw3_press = false; //reset switch
} else {
/* No state change - nothing to do. Poll again. */
continue;
}
lcd_clear();
if (pause_flag){
RESET_ALL_LEDS();
jet_x = 0;
jet_y = 0;
Set_Font_Bitmap(); //changes from text mode to bitmap
Set_LCD_Pos(jet_x,jet_y);
Set_LCD_Char(3);
} else {
ALL_RED_LEDS_ON();
Set_Font_8_by_8();
lcd_display(LCD_LINE1, " PAUSED ");
}
}
I'm trying to create an Etch-n-sketch game and when I move the arrow keys up and down, the cursor moves to the right and in what ever direction I pressed. I can move right, though it appears to be skipping a spot and I cant move left
Code for moving and drawing:
void moveCursor(char input)
{
int cursorX_Pos;
int cursorY_Pos;
int arrows;
getyx(stdscr, cursorY_Pos, cursorX_Pos);
arrows = 1;
switch(input)
{
case UP:
cursorY_Pos--;
arrows = 0;
break;
case DOWN:
cursorY_Pos++;
arrows = 0;
break;
case RIGHT:
cursorX_Pos++;
arrows = 0;
break;
case LEFT:
cursorX_Pos--;
arrows = 0;
break;
default:
arrows = 1;
break;
}
if (arrows == 0)
{
draw(cursorY_Pos,cursorX_Pos);
}
}
void draw(int y, int x)
{
mvaddch(y, x, '#');
refresh();
}
I'm not really sure where the code is trying to move diagonal. I tried splitting up the mvaddch into move and addch. I tried them at diffrent times and the move works (doesnt appear to be skipping) but when I enable the addch part, it skips and goes diagonal. How do I do fix this?
When you add a character to the screen, the cursor moves to the position after it. So, when you then fetch the current cursor position, it's one cell to the right of where you moved to, before adding the character. Thus, when trying to move left, for instance: you're subtracting 1 in moveCursor(), and adding 1 back in draw().
Either subtract 1 from cursorX_pos after the getyx(), or perhaps, maintain your coordinate values independent of curses' idea of where the cursor is (i.e. just leave out the getyx()).
For bonus points, realize that the target coordinates (for the next draw) and the current position are two different things, and optimize accordingly. (Hint: moving right shouldn't require a move() at all.)
I am making a project in C. Its simple, just a Hangman Game.
Got the logic already cause I've done that only in console.
Now, I'm trying to do it in C again with GRAPHICS. I am using Turbo C.
I've read some of the functions of graphics.h: so far I've seen outtext() / outtextxy() something like that. It can print a string.
Can you input a char or string in graphics? Searched a lot but seen nothing.
Seen only drawing shapes examples.
How do you input characters, integers etc. in the graphics mode?
From memory, while you can use regular stdio functions printf, scanf, and gets, the graphics driver will paint them over your screen onto a "virtual cursor" position and scroll the screen when it reaches the bottom. You can use the nonstandard conio.h functions such as gotoxy and attempt to position the cursor, but it's still a mediocre way of inputting text, messing up the graphics stuff. You also cannot use the fancy fonts!
So use getch to read characters without showing them; update a string buffer (manually handling special keys such as Backspace and Return), and draw that on the screen using a font of your choice.
A short sample snippet of code to get you started:
#define MAX_INPUT_LEN 80
char inputbuf[MAX_INPUT_LEN];
int input_pos = 0;
then, in your main loop
int the_end = 0;
do
{
outtextxy (0,0, inputbuf);
c = getch();
switch (c)
{
case 8: /* backspace */
if (input_pos)
{
input_pos--;
inputbuf[input_pos] = 0;
}
break;
case 13: /* return */
the_end = 1;
break;
case 27: /* Escape = Abort */
inputbuf[0] = 0;
the_end = 1;
break;
default:
if (input_pos < MAX_INPUT_LEN-1 && c >= ' ' && c <= '~')
{
inputbuf[input_pos] = c;
input_pos++;
inputbuf[input_pos] = 0;
}
}
} while (!the_end);
Before you draw the text, make sure to erase the previous line! I left that out because it's been too long ago I used Turbo-C.
For taking input from used.. you can use scanf function similar to how we take input in any non-graphics c program.
You can do this by using normal scanf function. And by using sprintf copy a integer/whatever variable into a string. Now you can use outtextxy to set the string in specified location using x,y axis. Check geeksforgeeks to learn sprintf syntax.
I know it is too late. Hope it helps someone else.!
I write a client for a console game, 1vs1. In the game one player have to catch the other, and every player is rappresented with a char, printed on the console. I use the mvaddch() to delete the old position, and to print the new position on the console.
My code generate 2 process:
Process A: It get the input from the keyboard and update the position on the screen;
Process B: it get the input from the server and update the position of the enemy on the screen;
My problem is the old position of the enemy is not deleted (overwriting with ' '), and so process B generates a snake of charactes on the screen. Process A work good.
initscr();
noecho();
curs_set(0);
//process A is created now
switch ( pid = fork() ) {
case -1: perror("fork() fallita"); exit(0);
case 0: {char c; struct pos old_position = {welcome_position.c, welcome_position.x, welcome_position.y};
struct pos position = {welcome_position.c, welcome_position.x, welcome_position.y};
mvaddch(position.y, position.x, position.c);
while (1) {
switch(c=getch()) {
case SU: if(position.y>0) { position.y-=1; } break;
case GIU: if(position.y<MAXY-1){ position.y+=1; } break;
case SINISTRA: if(position.x>0){ position.x-=1; } break;
case DESTRA: if(position.x<MAXX-1){ position.x+=1; } break;
default: break; }
if ((position.x != old_position.x) || (position.y != old_position.y)) {
send(sock, &position, sizeof(struct pos), 0);
mvaddch(old_position.y, old_position.x, ' ');
mvaddch(position.y, position.x, position.c);
refresh();
old_position.x = position.x;
old_position.y = position.y; }} }
default: break ; }
// Process B is here
struct pos position;
struct pos old_position={' ', -1,-1};
while (1) {
while ( recv(sock, &position, sizeof(struct pos), 0) < 1 )
mvaddch(old_position.y, old_position.x, ' '); // THE PROBLEM
mvaddch(position.y, position.x, position.c); // Works => snake
refresh();
old_position.x = position.x;
old_position.y = position.y;}
endwin();
kill(pid);
printf("\n-----------------------------\n");
}
If you don't want the entire trail showing, you have to keep a record of the previous position of each character (player) and arrange to write a blank at the old position and the correct mark at the new position. If you're feeling fancy, you might use a coloured blank, one colour for each player, so you can see where each has been, even though the current positions are marked differently.
Unfortunately, without the colouration mentioned, that looks like what you're doing.
You should make sure you don't use the -1 coordinates; mvaddch() is probably not error checked and will go trampling out of bounds, doing who knows what damage. Don't risk it. (Consider using 0, 0 as the old position; it won't matter if you write a blank over a blank. The only thing that matters is that the other player is not where you write the blank.)
Note that it is crucial that only one process is doing the drawing. If you have two processes attempting to do so, you will lose one or the other images some of the time. This is one reason reason why it is hard to add a clock, say, to the top right corner of a terminal screen. You do seem to have two processes trying to write to the screen.
Style-wise, you need to use more functions. That is, the different processes should each have their code in a separate function, so that it is easier to see what they are doing. Stacking close braces } three deep on a single line is not good style either.