SDL - Update Surface in C - c

i use SDL Lib and SDL_TTF Lib
I have a code that allows you to enter text
And then display the text on my window
so here the code
TTF_Init();
SDL_Init(SDL_INIT_VIDEO);
TTF_Font * font = TTF_OpenFont("C:\\Windows\\Fonts\\Arial.ttf", 25);
SDL_Color color = { 255, 255, 255 };
SDL_Surface * surface = TTF_RenderText_Solid(font,"", color);
SDL_Window * window = SDL_CreateWindow("SDL_ttf in SDL2",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640,
480, 0);
SDL_Renderer * renderer = SDL_CreateRenderer(window, -1, 0);
SDL_Texture * texture = SDL_CreateTextureFromSurface(renderer, surface);
int texW = 200;
int texH = 200;
SDL_QueryTexture(texture, NULL, NULL, &texW, &texH);
SDL_Rect dstrect = { 200, 200, texW, texH };
SDL_RenderCopy(renderer, texture, NULL, &dstrect);
SDL_RenderPresent(renderer);
while (program_launched)
{
SDL_bool has_type = SDL_FALSE;
SDL_WaitEvent(&event);
if(event.type == SDL_QUIT)
program_launched = SDL_FALSE;
else if( event.type == SDL_KEYDOWN)
{
if(event.key.keysym.sym == SDLK_BACKSPACE && len)
{
rep[len - 1] = 0;
len--;
has_type = SDL_TRUE;
}
if(event.key.keysym.sym == SDLK_v && (SDL_GetModState() & KMOD_CTRL) && SDL_HasClipboardText())
{
char *tmp = SDL_GetClipboardText();
size_t l = strlen(tmp);
size_t l_copy = len + l < LEN_MAX ? l : LEN_MAX - len;
strncpy(rep + len, tmp, l_copy);
len += l_copy;
SDL_free(tmp);
has_type = SDL_TRUE;
}
if(event.key.keysym.sym == SDLK_c && (SDL_GetModState() & KMOD_CTRL))
SDL_SetClipboardText(rep);
}
else if(event.type == SDL_TEXTINPUT)
{
size_t l = strlen(event.text.text);
size_t l_copy = len + l < LEN_MAX ? l : LEN_MAX - len;
strncpy(rep + len, event.text.text, l_copy);
len += l_copy;
has_type = SDL_TRUE;
}
if(has_type)
surface = TTF_RenderText_Solid(font,rep, color);
texture = SDL_CreateTextureFromSurface(renderer, surface);
SDL_QueryTexture(texture, NULL, NULL, &texW, &texH);
SDL_Rect dstrect = { 0, 0, texW, texH };
SDL_RenderCopy(renderer, texture, NULL, &dstrect);
SDL_RenderPresent(renderer);
}
It's to (has-type) that I display the buff (rep)
But my problem is here:
I can write and display in the window a text
But if i do a backspace and i write
The texts overlap because the window, at least the rectangle is not updated
Is it possible to delete the content of my window (to display the buff without overlapping) ?
I use this documentation
https://www.libsdl.org/projects/SDL_ttf/docs/SDL_ttf.pdf
I had tried with this function: SDL_UpdateWindowSurface(window);
But nothing helps
Compiler: GCC
OS: Windows

It's because once you've outputed something to the screen, it stays there unless you clear it or put something above it.
Think of it as a painter plotting things on his canvas. If you want to overwrite something, you have to overwrite the previous shape.
The simplest way to deal with this would be to call SDL_RenderClear at the beginning of every draw, it clears the whole screen clean, and then every time you render something it'll never overlap the previous stuff.

Related

How to use text in EFI graphic mode?

I am super new to creating efi application. My aim is to create a small application in efi, that displays some text on a background. But I am stuck with trying to display text on the display (Great would be to have a custom font, but that is not necessary at this stage). I want the app (also) to run on apple systems (to boot from a usb)
How do I find good documentation on the EFI functions? It seems super hard to find good examples etc.
How can I display a text on a background with EFI?
This is what I got so far. I change the background to a color using the graphics protocol. How do I display a text on it. The Output String doesn't seem to work.
#include "efibind.h"
#include "efidef.h"
#include "efidevp.h"
#include "eficon.h"
#include "efiapi.h"
#include "efierr.h"
#include "efiprot.h"
static EFI_GUID GraphicsOutputProtocolGUID = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
/**
* efi_main - The entry point for the EFI application
* #image: firmware-allocated handle that identifies the image
* #SystemTable: EFI system table
*/
EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *systemTable) {
EFI_BOOT_SERVICES *bs = systemTable->BootServices;
EFI_STATUS status;
EFI_GRAPHICS_OUTPUT_PROTOCOL *graphicsProtocol;
SIMPLE_TEXT_OUTPUT_INTERFACE *conOut = systemTable->ConOut;
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *info;
UINTN SizeOfInfo, sWidth, sHeight;
status = bs->LocateProtocol(&GraphicsOutputProtocolGUID, NULL,
(void**)&graphicsProtocol);
if (EFI_ERROR(status) || graphicsProtocol == NULL) {
conOut->OutputString(conOut, L"Failed to init gfx!\r\n");
return status;
}
conOut->ClearScreen(conOut);
//Switch to current mode so gfx is started.
status = graphicsProtocol->SetMode(graphicsProtocol, graphicsProtocol->Mode->Mode);
if (EFI_ERROR(status)) {
conOut->OutputString(conOut, L"Failed to set default mode!\r\n");
return status;
}
EFI_GRAPHICS_OUTPUT_BLT_PIXEL p;
p.Red = 200;
p.Green = 77;
p.Blue = 13;
graphicsProtocol->QueryMode(graphicsProtocol, graphicsProtocol->Mode->Mode, &SizeOfInfo, &info);
sWidth = info->HorizontalResolution;
sHeight = info->VerticalResolution;
status = graphicsProtocol->Blt(graphicsProtocol, &p, EfiBltVideoFill, 0, 0, 0, 0, sWidth, sHeight, 0);
while (1) {
conOut->OutputString(conOut, L"Some text that I want to display\r\n");
bs->Stall(500000);
}
return EFI_SUCCESS;
}
UEFI supports graphics output. It also supports text output (which can mean either output to a serial console, or text rendered to a graphical console, or both). But there is no defined way to interact between these in a controlled manner.
Applications that provide a graphical environment with text elements (BIOS configuration menu, GRUB) generally do this using their own frameworks to draw text on the graphical console using GRAPHICS_OUTPUT_PROTOCOL.
This is a short example of a text renderer using the font module from LVGL (which can be used standalone, replace #include "../../lv_conf.h" in the lv_font.h file with #define USE_LV_FONT_DEJAVU_20 8) and the Blt method from the GRAPHICS_OUTPUT_PROTOCOL
#include <Uefi.h>
#include <Library\UefiLib.h>
#include <Protocol\GraphicsOutput.h>
#include "lv_font.h"
#define LETTER_SPACE 2
#define WAIT_SECONDS 10
#define FONT &lv_font_dejavu_20
static EFI_BOOT_SERVICES *gBS;
static EFI_RUNTIME_SERVICES *gRT;
static EFI_GRAPHICS_OUTPUT_PROTOCOL *gGOP = (EFI_GRAPHICS_OUTPUT_PROTOCOL *)NULL;
static EFI_GRAPHICS_OUTPUT_BLT_PIXEL gWhite = { 255,255,255,0 };
static void _util_render_glyph(UINT32 x, UINT32 y, CHAR8 letter)
{
UINT32 height;
UINT32 width;
UINT32 pm_x;
UINT32 pm_y;
UINT32 index;
const UINT8* bitmap;
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *pixelmap;
if (gGOP == NULL) {
return;
}
height = lv_font_get_height(FONT);
width = lv_font_get_width(FONT, letter);
// glyph is not defined in this font
if (width == 0) {
return;
}
bitmap = lv_font_get_bitmap(FONT, letter);
// using 8 bpp for simplicity
if (EFI_ERROR(gBS->AllocatePool(EfiLoaderData, height * width * sizeof(*pixelmap), (VOID**)&pixelmap))) {
return;
}
gBS->SetMem((VOID*)pixelmap, height * width * sizeof(*pixelmap), 0);
// get the current content of the framebuffer to allow 'transparent' blt operations
gGOP->Blt(gGOP, pixelmap, EfiBltVideoToBltBuffer, x, y, 0, 0, width, height, 0);
for (pm_y = 0; pm_y < height; pm_y++) {
for (pm_x = 0; pm_x < width; pm_x++) {
index = width * pm_y + pm_x;
if (bitmap[index] > 200) {
pixelmap[index].Red = 0;
pixelmap[index].Blue = 0;
pixelmap[index].Green = 0;
pixelmap[index].Reserved = 0;
}
else if (bitmap[index] > 100) {
pixelmap[index].Red = 105;
pixelmap[index].Blue = 105;
pixelmap[index].Green = 105;
pixelmap[index].Reserved = 0;
}
}
}
gGOP->Blt(gGOP, pixelmap, EfiBltBufferToVideo, 0, 0, x, y, width, height, 0);
gBS->FreePool(pixelmap);
}
static void _util_render_text(UINT32 x, UINT32 y, const CHAR8 *string)
{
UINT32 index;
UINTN length;
UINT32 scr_w;
UINT32 scr_h;
UINT32 str_x;
UINT32 gly_w;
UINT32 gly_h;
if (string == NULL) {
return;
}
if (gGOP == NULL) {
return;
}
scr_w = gGOP->Mode->Info->HorizontalResolution;
scr_h = gGOP->Mode->Info->VerticalResolution;
length = AsciiStrnLenS(string, 32);
gly_h = lv_font_get_height(FONT);
// check if the string can be printed
if ((y + gly_h) > scr_h) {
return;
}
if (x > scr_w) {
return;
}
// print the string glyph by glyph
str_x = x;
for (index = 0; index < length; index++) {
// check if the glyph can be printed
gly_w = lv_font_get_width(FONT, string[index]);
if ((str_x + gly_w) > scr_w) {
break;
}
// print the glyph
_util_render_glyph(str_x, y, string[index]);
// calculate the position of the next glyph
str_x += gly_w + LETTER_SPACE;
}
}
static void _util_fill_screen(EFI_GRAPHICS_OUTPUT_BLT_PIXEL *color)
{
if (gGOP == NULL) {
return;
}
gGOP->Blt(gGOP, color, EfiBltVideoFill, 0, 0, 0, 0, gGOP->Mode->Info->HorizontalResolution, gGOP->Mode->Info->VerticalResolution, 0);
}
static void _util_wait(UINT32 seconds)
{
EFI_TIME time;
UINT8 current_second = 255;
UINT32 elapsed_seconds = 0;
//wait for some seconds
while (elapsed_seconds <= WAIT_SECONDS) {
if (!EFI_ERROR(gRT->GetTime(&time, (EFI_TIME_CAPABILITIES*)NULL))) {
if (current_second != time.Second) {
elapsed_seconds++;
current_second = time.Second;
}
}
else {
break;
}
CpuPause();
}
}
EFI_STATUS
EFIAPI
UefiMain(
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable)
{
EFI_STATUS eRc;
gBS = SystemTable->BootServices;
gRT = SystemTable->RuntimeServices;
eRc = gBS->LocateProtocol(
&gEfiGraphicsOutputProtocolGuid,
NULL,
(VOID**)&gGOP);
if (EFI_ERROR(eRc) || gGOP == NULL) {
return EFI_SUCCESS;
}
_util_fill_screen(&gWhite);
_util_render_text(0, 0, "HELLO WORLD!");
_util_wait(WAIT_SECONDS);
return EFI_SUCCESS;
}
I tested it on a pc and on a mac it runs on both. Using the tools provided by LVGL on their website you can use any font you want.
If you target MacEFI specifically, you'll need an additional protocol call to force the console into text mode, like this.

IMG_Load: Couldn't open xxx.png

Context: I am currently trying to practice my C skills a little bit with the SDL 2.0.7 and SDL2_image-2.0.2.
Problem: I get an error message during the execution of my program "IMG_Load: Couldn't open xxx.png". The error seems stupid as it is very explicit: "i can't find the image", but as the image is in the appropriate folder... I think I need a fresh eye to spot the stupid mistake.
Platform: Windows 10
IDE: Visual Studio 2017
Steps done to solve the problem:
1) Tried to reduce my code lenght/functionalities to its minimum. Result: Error is still here.
2) I created a new project and copy/pasted the simplified code. Result: On the new project, there is no error, everything is working fine.
3) I compared project's options and the folder. To me they are the same:
It shouldn't be useful but just in case, here is my:
Code sample:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <SDL.h>
#include <SDL_image.h>
#include <SDL_render.h>
#include "SDL_timer.h"
int main(int argc, char *argv[])
{
printf("argc = %d\n", argc);
for (int i = 0; i < argc; ++i)
{
printf("argv[ %d ] = %s\n", i, argv[i]);
}
SDL_Window* pWindow = NULL;
SDL_Renderer* pRenderer = NULL;
SDL_Texture* pTexture = NULL;
SDL_Surface* pLoadedSurface = NULL;
SDL_Rect* tileClipsArray = NULL;
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER))
{
fprintf(stderr, "Erreur d'initialisation de la SDL : %s\n", SDL_GetError());
}
//Initialize PNG loading
int imgFlags = IMG_INIT_PNG;
if (!(IMG_Init(imgFlags) & imgFlags))
{
printf("IMG_Load: %s\n", IMG_GetError());
}
pWindow = SDL_CreateWindow("TestLoadingImage",
SDL_WINDOWPOS_CENTERED, // initial X position.
SDL_WINDOWPOS_CENTERED, // Initial Y position.
640, // Width, in pixels.
480, // Height, in pixels.
SDL_WINDOW_OPENGL); // Window flags
assert(NULL != pWindow);
//Create renderer for the window
pRenderer = SDL_CreateRenderer(pWindow,
-1, // Index of the rendering driver to initialize, -1 to initialize the first one supporting the requested flags.
SDL_RENDERER_ACCELERATED
| SDL_RENDERER_PRESENTVSYNC); // RendererFlags
assert(NULL != pRenderer);
//Initialize renderer color
SDL_SetRenderDrawColor(pRenderer, 0xFF, 0xFF, 0xFF, 0xFF);
pLoadedSurface = IMG_Load("GroundTiles.png");
if (NULL == pLoadedSurface)
{
printf("IMG_Load: %s\n", IMG_GetError());
assert(NULL != pLoadedSurface);
}
//Create texture from surface pixels
pTexture = SDL_CreateTextureFromSurface(pRenderer, pLoadedSurface);
assert(NULL != pTexture);
//Get image dimensions
const int textureWidth = pLoadedSurface->w;
const int textureHeight = pLoadedSurface->h;
const int tileClipWidth = 128;
const int tileClipHeight = 128;
const int nbLines = textureHeight / tileClipHeight;
const int nbColumns = textureWidth / tileClipWidth;
const int nbTileClips = nbLines + nbColumns;
tileClipsArray = malloc(nbTileClips * sizeof(SDL_Rect));
int tileClipIndex = 0;
for (int tileClipLineIndex = 0; tileClipLineIndex < nbLines; ++tileClipLineIndex)
{
for (int tileClipColumnIndex = 0; tileClipColumnIndex < nbColumns; ++tileClipColumnIndex)
{
tileClipsArray[tileClipIndex].x = tileClipColumnIndex * tileClipWidth;
tileClipsArray[tileClipIndex].y = tileClipLineIndex * tileClipHeight;
tileClipsArray[tileClipIndex].w = tileClipWidth;
tileClipsArray[tileClipIndex].h = tileClipHeight;
++tileClipIndex;
}
}
//Get rid of old loaded surface
SDL_FreeSurface(pLoadedSurface);
pLoadedSurface = NULL;
int canLoop = 1;
SDL_Event event;
int lastUpdate = SDL_GetTicks();
int now = 0;
int timeToSpendPerClip = 5000;
int timeSpentwithThisClip = 0;
int clipToUse = 0;
while (canLoop)
{
now = SDL_GetTicks();
if (now - lastUpdate > 16)
{
timeSpentwithThisClip += now - lastUpdate;
lastUpdate = now;
// We are processing all the events received this frame.
while (SDL_PollEvent(&event))
{
// We need to know what kind of event we are dealing with.
switch (event.type)
{
case SDL_QUIT:
canLoop = 0;
break;
}
}
SDL_RenderClear(pRenderer);
if (timeSpentwithThisClip > timeToSpendPerClip)
{
clipToUse = rand() % 4;
timeSpentwithThisClip = 0;
}
// Set rendering space and render to screen.
SDL_Rect renderQuad;
renderQuad.x = 50;
renderQuad.y = 50;
renderQuad.w = tileClipsArray[clipToUse].w;
renderQuad.h = tileClipsArray[clipToUse].h;
SDL_RenderCopyEx(pRenderer, pTexture, &tileClipsArray[clipToUse], &renderQuad, 0.0, NULL, SDL_FLIP_NONE);
SDL_RenderPresent(pRenderer);
}
}
SDL_DestroyTexture(pTexture);
free(tileClipsArray);
SDL_DestroyRenderer(pRenderer);
pRenderer = NULL;
SDL_DestroyWindow(pWindow);
pWindow = NULL;
IMG_Quit();
SDL_Quit();
return EXIT_SUCCESS;
}
I'm probably going to copy/paste all my files from the project 1 into the project 2, but I would like to understand my mistake!

How can i add line breaks when rendering Text using X11,

I am making an application that renders texts according to style mentioned on screen using X Windows System and Xft. My code is working fine as shown below.
#include <X11/Xlib.h>
#include <X11/Xft/Xft.h>
char * nowShowing()
{
return strdup("This is a sample text This is rendered with new Driver installed This is a sample text his is rendered with new Driver installed");
}
int main()
{
XftFont *font;
XftDraw *draw;
XRenderColor render_color;
XftColor xft_color;
char *str;
str = nowShowing();
int x = 70;
int y = 150;
Display *dis = XOpenDisplay (0);
int screen = DefaultScreen (dis);
Window w = XCreateSimpleWindow (dis, RootWindow (dis, screen),
0, 0, 1200, 300, 1,
BlackPixel (dis, screen),
WhitePixel (dis, screen));
XEvent ev;
render_color.red = 0;
render_color.green =0;
render_color.blue = 0;
render_color.alpha = 0xffff;
XftColorAllocValue (dis,
DefaultVisual(dis, screen),
DefaultColormap(dis, screen),
&render_color,
&xft_color);
//font = XftFontOpen(dis, screen,
// XFT_FAMILY, XftTypeString, "charter",
// XFT_SIZE, XftTypeDouble, 20.0,
// NULL);
font = XftFontOpenName(dis,screen,"URW Palladio L:style=Bold Italic"); //it takes a Fontconfig pattern string
draw = XftDrawCreate(dis, w,
DefaultVisual(dis, screen),
DefaultColormap(dis, screen));
XSelectInput (dis, w, ExposureMask);
XMapWindow (dis, w);
for (;;)
{
XNextEvent (dis, &ev);
if (ev.type == Expose)
XftDrawString8(draw, &xft_color, font, x, y, (XftChar8 *) str,
strlen(str));
}
return 0;
}
But i am wondering that how can i add line breaks in the text entered. I tried using "/n" and also tried to make array and used loops but it didn't work.
New line "\n" will not be rendered by Xft. You need to render each line separately with proper offset, depending on font size and desired spacing.
I have modified the ending block of your code with sample text rendered two times on separate lines.
if (ev.type == Expose)
{
int fonth = font->ascent + font->descent;
XftDrawString8(draw, &xft_color, font, x, y, (XftChar8 *) str,
strlen(str));
XftDrawString8(draw, &xft_color, font, x, y+fonth, (XftChar8 *) str,
strlen(str));
}

Color key transparency does not work with SDL_image and PNG files

I am trying to achieve transparency in SDL using color keying. While it does work with BMP files, it doesn't with PNG files.
Here is my code:
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
int main(int argc, char *argv[])
{
SDL_Init(SDL_INIT_EVERYTHING);
SDL_Surface *displaySurface = SDL_SetVideoMode(200, 100, 32, SDL_HWSURFACE | SDL_DOUBLEBUF);
SDL_Surface *tmpSurface = NULL;
SDL_Surface *backgroundSurface = NULL;
SDL_Surface *bmpSurface = NULL;
SDL_Surface *pngSurface = NULL;
tmpSurface = IMG_Load("background.png");
backgroundSurface = SDL_DisplayFormat(tmpSurface);
SDL_FreeSurface(tmpSurface);
tmpSurface = SDL_LoadBMP("bmpImage.bmp");
bmpSurface = SDL_DisplayFormat(tmpSurface);
SDL_FreeSurface(tmpSurface);
SDL_SetColorKey(bmpSurface, SDL_SRCCOLORKEY | SDL_RLEACCEL, SDL_MapRGB(bmpSurface->format, 255, 0, 255));
tmpSurface = IMG_Load("pngImage.png");
pngSurface = SDL_DisplayFormat(tmpSurface);
SDL_FreeSurface(tmpSurface);
SDL_SetColorKey(pngSurface, SDL_SRCCOLORKEY | SDL_RLEACCEL, SDL_MapRGB(pngSurface->format, 255, 0, 255));
SDL_Rect dest;
dest.x = 0;
dest.y = 0;
SDL_BlitSurface(backgroundSurface, NULL, displaySurface, &dest);
SDL_BlitSurface(bmpSurface, NULL, displaySurface, &dest);
dest.x = 50;
SDL_BlitSurface(pngSurface, NULL, displaySurface, &dest);
SDL_Flip(displaySurface);
SDL_Event event;
while (1) {
while (SDL_PollEvent(&event)) {
;
}
SDL_Delay(1);
}
return 0;
}
I have uploaded both the code and the images I am using here:
http://tobias.braun-abstatt.de/files/forums/transparency_test.zip
If you are using SDL_image version 1.2.10 or 1.2.11, make sure to update it to version 1.2.12.
#include <SDL/SDL_image.h>
#if (SDL_IMAGE_MAJOR_VERSION != 1) || (SDL_IMAGE_MINOR_VERSION != 2) || (SDL_IMAGE_PATCHLEVEL < 12)
#error "Invalid SDL_image version"
#endif

Checkers game in SDL

i'm trying to make a checkers game and atm i'm doing the interface with SDL, but i'm just learning C and SDL, how can I move a surface I added to the screen ? I want it the simplest as possible, just remove from X and show on Y, how do I remove a surface to make it appear on another place on the screen ? here is my code:
#include "SDL.h"
#define BRANCA 2
#define PRETA 1
#define DAMA 2
#define NORMAL 1
//The attributes of the screen
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
const int SCREEN_BPP = 32;
//The surfaces that will be used
SDL_Surface *pecaPreta = NULL;
SDL_Surface *pecaBranca = NULL;
SDL_Surface *pecaDamaPreta = NULL;
SDL_Surface *pecaDamaBranca = NULL;
SDL_Surface *background = NULL;
SDL_Surface *screen = NULL;
SDL_Event event;
SDL_Surface *load_image(char * filename )
{
SDL_Surface* loadedImage = NULL;
SDL_Surface* optimizedImage = NULL;
loadedImage = SDL_LoadBMP(filename);
if( loadedImage != NULL )
{
optimizedImage = SDL_DisplayFormat( loadedImage );
SDL_FreeSurface( loadedImage );
if( optimizedImage != NULL )
{
Uint32 colorkey = SDL_MapRGB( optimizedImage->format, 0, 0xFF, 0xFF );
SDL_SetColorKey( optimizedImage, SDL_SRCCOLORKEY, colorkey );
}
}
return optimizedImage;
}
void apply_surface( int x, int y, SDL_Surface* source, SDL_Surface* destination )
{
SDL_Rect offset;
offset.x = x;
offset.y = y;
SDL_BlitSurface( source, NULL, destination, &offset );
}
void inserePeca(int tipo, int posX, int posY, int cor)
{
switch(cor)
{
case 1:
switch (tipo)
{
case 1:
apply_surface(posX, posY, pecaPreta, screen);
break;
case 2:
apply_surface(posX, posY, pecaDamaPreta, screen);
break;
}
break;
case 2:
switch (tipo)
{
case 1:
apply_surface(posX, posY, pecaBranca, screen);
break;
case 2:
apply_surface(posX, posY, pecaDamaBranca, screen);
break;
}
break;
}
}
int main()
{
int quit = 0;
if( SDL_Init( SDL_INIT_EVERYTHING ) == -1 )
{
return 1;
}
screen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE );
if( screen == NULL )
{
return 1;
}
//Set the window caption
SDL_WM_SetCaption( "Jogo de Damas 0.1b", NULL );
//Load the images
pecaPreta = load_image( "pecapreta.bmp" );
pecaBranca = load_image("pecabranca.bmp");
pecaDamaPreta = load_image("pecadamapreta.bmp");
pecaDamaBranca = load_image("pecadamabranca.bmp");
background = load_image( "tabuleiro.bmp" );
//Apply the background to the screen
apply_surface( 0, 0, background, screen );
inserePeca(DAMA, 0,0, BRANCA);
inserePeca(NORMAL, 80,0, PRETA);
//Update the screen
if( SDL_Flip( screen ) == -1 )
{
return 1;
}
while( quit == 0 )
{
//While there's an event to handle
while( SDL_PollEvent( &event ) )
{
//If the user has Xed out the window
if( event.type == SDL_QUIT )
{
//Quit the program
quit = -1;
}
}
}
//Free the surfaces
SDL_FreeSurface( pecaPreta );
SDL_FreeSurface( background );
//Quit SDL
SDL_Quit();
return 0;
}
as you can see I add a block on "inserePeca", I want to move it after I create it
The buffer for the screen doesn't keep all the things you draw on it as separate items -- it just holds the end result of all the drawing operations. So, you can't just draw the background, then draw a piece on it, then move the piece around -- you need to redraw the affected parts of the screen with the required changes.
You still have the images of the pieces, and you still have the background image; the way to move a piece you've drawn is simply to restore the background to the old position by blitting it again, and then blit the piece in the new position. Rather than drawing the whole screen and all the pieces over again, though, you can just draw the changed areas: blit just a part of the background to erase the old square, and then blit the piece onto the new square.
The following function is similar to your apply_surface() function, but instead of copying the whole source image to the the given coordinates of the destination, it copies a region of a given width and height from the given coordinates of the source image to the same coordinates of the destination. This can then be used to restore the background for a small part of the screen.
/* Blit a region from src to the corresponding region in dest. Uses the same
* x and y coordinates for the regions in both src and dest. w and h give the
* width and height of the region, respectively.
*/
void erase_rect( int x, int y, int w, int h, SDL_Surface *src, SDL_Surface *dest)
{
SDL_Rect offset;
offset.x = x;
offset.y = y;
offset.w = w;
offset.h = h;
SDL_BlitSurface( src, &offset, dest, &offset );
}
So if your squares are 50x50, and you need to move a piece from a square at (120, 40) to the square at (170, 90), you could do something like the following:
/* erase old 50x50 square at (120,40) (to background image) */
erase_rect( 120, 40, 50, 50, background, screen );
/* draw piece at new position of (170,90) */
inserePeca(NORMAL, 170, 90, PRETA);

Resources