Related
I'm trying to create a simple camera for my SDL2 platformer with C. However, whenever the player reaches the screen edges, it seems to be cut off by the background. Here is what the player looks like normally:
And here is what the player looks like when it reaches the screen edges:
To make the camera follow the player, I'm just creating a SDL_Rect called camera, setting it to the player x and y positions, and setting the viewport with SDL_RenderSetViewport to the camera rectangle.
Here's the code for that:
void handle_camera() {
SDL_Rect camera = {
.x = WIDTH/2 - player.x - BLOCK_SIZE/2,
.y = HEIGHT/2 - player.y - BLOCK_SIZE/2,
.w = WIDTH,
.h = HEIGHT
};
SDL_RenderSetViewport(game.renderer, &camera);
}
Therefore, I was wondering: what's wrong with my camera function and why is the player being cut off when it gets near the screen edges?
Here is the full code if needed (I organized in functions so I hope it's not too hard to understand):
#include <stdio.h>
#include <stdbool.h>
#include <SDL2/SDL.h>
#define WIDTH 1200
#define HEIGHT 800
#define BLOCK_SIZE 50
#define PLATFORM_AMOUNT 11 //This makes sure there are enough iterations of the loop, and also allocates enough memory for the 2D array of platforms.
#define LAVA_AMOUNT 2
#define TRAMPOLINE_AMOUNT 1
//Prototyping Functions
int initialize();
void handle_input();
void draw_player();
void player_moveX();
void player_moveY();
void checkCollisionsX();
void checkCollisionsY();
int rectCollide();
void drawLevel();
void resetPlayer();
void handle_camera();
typedef struct {
SDL_Renderer *renderer;
SDL_Window *window;
SDL_Surface *surface;
bool running;
int FPS;
bool close_requested;
int input[256];
} Game;
Game game = {
.running = true,
.FPS = 80,
.close_requested = false,
.input = {},
};
typedef struct {
int x;
int y;
double x_vel;
double y_vel;
double x_acc;
double y_acc;
int width;
int height;
double accSpeed;
int maxVel;
double gravity;
double friction;
double jumpForce;
double canJump;
} Player;
Player player = {
.y = HEIGHT-(BLOCK_SIZE*2),
.x = BLOCK_SIZE,
.x_vel = 0,
.y_vel = 0,
.x_acc = 0,
.y_acc = 0,
.width = BLOCK_SIZE,
.height = BLOCK_SIZE,
.accSpeed = 0.15,
.maxVel = 7,
.gravity = 0.5,
.friction = 0.15,
.jumpForce = 15,
.canJump = true,
};
int platforms[PLATFORM_AMOUNT][4] = {
{0, 0, BLOCK_SIZE, HEIGHT}, //WALLS
{0, HEIGHT-BLOCK_SIZE, WIDTH, BLOCK_SIZE},
{400-BLOCK_SIZE, HEIGHT-(BLOCK_SIZE*2), BLOCK_SIZE, BLOCK_SIZE}, //RAMP TO LAVA
{400-BLOCK_SIZE, HEIGHT-(BLOCK_SIZE*3), BLOCK_SIZE, BLOCK_SIZE},
{300, HEIGHT-(BLOCK_SIZE*2), BLOCK_SIZE, BLOCK_SIZE},
{800, HEIGHT-(BLOCK_SIZE*2), BLOCK_SIZE, BLOCK_SIZE},
{800, HEIGHT-(BLOCK_SIZE*3), BLOCK_SIZE, BLOCK_SIZE},
{800+BLOCK_SIZE, HEIGHT-(BLOCK_SIZE*2), BLOCK_SIZE, BLOCK_SIZE},
{WIDTH-BLOCK_SIZE*10, HEIGHT-(BLOCK_SIZE*8), BLOCK_SIZE, BLOCK_SIZE}, //Blocks above lava
{WIDTH-BLOCK_SIZE*8, HEIGHT-(BLOCK_SIZE*10), BLOCK_SIZE, BLOCK_SIZE},
{BLOCK_SIZE, BLOCK_SIZE*3, BLOCK_SIZE*9, BLOCK_SIZE}, //Top platform
};
int lava[LAVA_AMOUNT][4] = {
{400, HEIGHT-(BLOCK_SIZE*3), 400, BLOCK_SIZE*2},
{BLOCK_SIZE*4, BLOCK_SIZE*2, BLOCK_SIZE*3, BLOCK_SIZE},
};
int trampoline[TRAMPOLINE_AMOUNT][4] = {
{WIDTH/2-(BLOCK_SIZE/2), HEIGHT-(BLOCK_SIZE*5), BLOCK_SIZE, BLOCK_SIZE}
};
int main() {
initialize();
while(game.running && !game.close_requested) { //Game loop
SDL_SetRenderDrawColor(game.renderer, 181, 247, 255, 255);
SDL_RenderClear(game.renderer);
handle_input();
handle_camera();
//Collisions only work in this order: playerMoveX, checkCollisionsX, playerMoveY, checkCollisionsY. Then you can draw the platforms and the player.
player_moveX();
checkCollisionsX();
player_moveY();
checkCollisionsY();
drawLevel();
draw_player();
SDL_RenderPresent(game.renderer);
SDL_Delay(1000/game.FPS);
} //End of game loop
SDL_DestroyRenderer(game.renderer);
SDL_DestroyWindow(game.window);
SDL_Quit();
return 0;
}
int initialize() {
if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER) != 0) { //return 0 on success
printf("error initializing SDL: %s\n", SDL_GetError());
return 1;
}
game.window = SDL_CreateWindow("Sam's Platformer", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WIDTH, HEIGHT, SDL_WINDOW_RESIZABLE); //creates window
if (!game.window) {
printf("error creating window: %s\n", SDL_GetError());
SDL_Quit();
return 1;
}
Uint32 render_flags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC; //creates a renderer
game.renderer = SDL_CreateRenderer(game.window, -1, render_flags);
if (!game.renderer) {
printf("error creating renderer: %s\n", SDL_GetError());
SDL_DestroyWindow(game.window);
SDL_Quit();
return 1;
}
return 0;
}
void handle_input() {
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
game.close_requested = true;
game.running = false;
}
//printf("input: %p code: %i\n", game.input, event.key.keysym.scancode);
if (event.type == SDL_KEYDOWN) {
game.input[event.key.keysym.scancode] = true;
//printf("True");
}
if (event.type == SDL_KEYUP) {
game.input[event.key.keysym.scancode] = false;
//printf("False");
}
}
if (game.input[SDL_SCANCODE_R]) {
resetPlayer();
}
}
void draw_player() {
SDL_Rect playerRect = {
.x = player.x,
.y = player.y,
.w = player.width,
.h = player.height
};
SDL_SetRenderDrawColor(game.renderer, 0, 200, 50, 255);
SDL_RenderFillRect(game.renderer, &playerRect);
}
void resetPlayer() {
player.y = HEIGHT-(BLOCK_SIZE*2);
player.x = BLOCK_SIZE;
player.x_vel = 0;
player.y_vel = 0;
}
void player_moveX() {
if (game.input[SDL_SCANCODE_LEFT] && player.x_vel > -player.maxVel) {
player.x_acc = -player.accSpeed;
} else if (game.input[SDL_SCANCODE_RIGHT] && player.x_vel < player.maxVel) {
player.x_acc = player.accSpeed;
} else if (abs(player.x_vel) > 0.2) {
if (player.x_vel < 0) {
player.x_acc = player.friction;
} else {
player.x_acc = -player.friction;
}
} else {
player.x_vel = 0;
player.x_acc = 0;
}
player.x_vel += player.x_acc;
player.x += player.x_vel;
}
void player_moveY() {
if (game.input[SDL_SCANCODE_UP] && player.y_vel == 0 && player.y_acc == 0 && player.canJump) {
player.canJump = false;
player.y_vel = -player.jumpForce;
}
player.y_acc += player.gravity;
player.y_vel += player.y_acc;
player.y += player.y_vel;
player.y_acc = 0;
}
void checkCollisionsX() {
for (int i = 0; i < PLATFORM_AMOUNT; i++) {
if (rectCollide(player.x, player.y, BLOCK_SIZE, BLOCK_SIZE, platforms[i][0], platforms[i][1], platforms[i][2], platforms[i][3])) {
if (player.x_vel < 0) { // If the player moved left and collided with the right side of block
player.x = platforms[i][0] + platforms[i][2];
} else { // If the player moved right and collided with the left side of block
player.x = platforms[i][0] - player.width;
}
player.x_vel = 0;
}
}
/*if (player.x >= WIDTH - player.width) {
player.x = WIDTH - player.width;
player.x_vel = 0;
}*/
for (int i = 0; i < LAVA_AMOUNT; i++) {
if (rectCollide(player.x, player.y, BLOCK_SIZE, BLOCK_SIZE, lava[i][0], lava[i][1], lava[i][2], lava[i][3])) {
resetPlayer();
}
}
for (int i = 0; i < TRAMPOLINE_AMOUNT; i++) {
if (rectCollide(player.x, player.y, BLOCK_SIZE, BLOCK_SIZE, trampoline[i][0], trampoline[i][1], trampoline[i][2], trampoline[i][3])) {
if (player.x_vel < 0) { // If the player moved left and collided with the right side of block
player.x = trampoline[i][0] + trampoline[i][2];
} else { // If the player moved right and collided with the left side of block
player.x = trampoline[i][0] - player.width;
}
player.x_vel = 0;
}
}
}
void checkCollisionsY() {
for (int i = 0; i < PLATFORM_AMOUNT; i++) {
if (rectCollide(player.x, player.y, player.width, player.height, platforms[i][0], platforms[i][1], platforms[i][2], platforms[i][3])) {
if (player.y_vel < 0) { // If the player hit their head
player.y = platforms[i][1] + platforms[i][3];
player.y_vel *= -0.5; // Not -1 because collisions are not perfectly elastic
} else {
player.y = platforms[i][1] - player.height;
player.y_vel = 0;
player.y_acc = 0;
player.canJump = true;
}
}
if (player.y >= HEIGHT - player.height) {
player.y_vel = 0;
player.y = HEIGHT - player.height;
if (!game.input[SDL_SCANCODE_UP]) {
player.canJump = true;
}
}
}
for (int i = 0; i < LAVA_AMOUNT; i++) {
if (rectCollide(player.x, player.y, BLOCK_SIZE, BLOCK_SIZE, lava[i][0], lava[i][1], lava[i][2], lava[i][3])) {
resetPlayer();
}
}
for (int i = 0; i < TRAMPOLINE_AMOUNT; i++) {
if (rectCollide(player.x, player.y, BLOCK_SIZE, BLOCK_SIZE, trampoline[i][0], trampoline[i][1], trampoline[i][2], trampoline[i][3])) {
if (player.y_vel < 0) { // If the player hit their head
player.y = trampoline[i][1] + trampoline[i][3];
player.y_vel *= -0.5; // Not -1 because collisions are not perfectly elastic
} else {
player.y = trampoline[i][1] - trampoline[i][3];
player.y_vel = -player.y_vel;
}
}
}
}
int rectCollide(int x1, int y1, int w1, int h1, int x2,int y2, int w2, int h2) {
return x1 + w1 > x2 && x1 < x2 + w2 && y1 + h1 > y2 && y1 < y2 + h2;
}
void drawLevel() {
for (int i = 0; i < PLATFORM_AMOUNT; i++) {
SDL_Rect platform = {platforms[i][0], platforms[i][1], platforms[i][2], platforms[i][3]};
SDL_SetRenderDrawColor(game.renderer, 156, 104, 0, 255);
SDL_RenderFillRect(game.renderer, &platform);
}
for (int i = 0; i < LAVA_AMOUNT; i++) {
int lavaRedColor = 255;
SDL_Rect lavaBlock = {lava[i][0], lava[i][1], lava[i][2], lava[i][3]};
SDL_SetRenderDrawColor(game.renderer, lavaRedColor, 0, 0, 255);
SDL_RenderFillRect(game.renderer, &lavaBlock);
}
for (int i = 0; i < TRAMPOLINE_AMOUNT; i++) {
SDL_Rect trampolineBlock = {trampoline[i][0], trampoline[i][1], trampoline[i][2], trampoline[i][3]};
SDL_SetRenderDrawColor(game.renderer, 235, 52, 229, 255);
SDL_RenderFillRect(game.renderer, &trampolineBlock);
}
}
void handle_camera() {
SDL_Rect camera = {
.x = WIDTH/2 - player.x - BLOCK_SIZE/2,
.y = HEIGHT/2 - player.y - BLOCK_SIZE/2,
.w = WIDTH, //Screen width
.h = HEIGHT //Screen height
};
SDL_RenderSetViewport(game.renderer, &camera);
}
Thanks for any help.
https://gamedev.stackexchange.com/questions/121421/how-to-use-the-sdl-viewport-properly
See this related post. Essentially changing the SDL viewport is not the way you'd typically handle an in game camera. You need to consider drawing your in game entities (level objects etc.) relative to the camera.
I wrote my implementation of vector ( dynamicly growing array) for integer type. And I was faced with a problem when using memmove and memcpy functions for data reallocation goals. Memmmove and memcpy functions work as not expected. So i replaced it with for and now it works properly. But what is the why memove works this way ?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct vector {
int v_size;
int v_length;
int* v_data;
} vector;
typedef vector *vect;
vect
new_vector(int size) {
vect tmp = (vector*)malloc(sizeof(vector));
tmp->v_size = size;
tmp->v_length = 0;
tmp->v_data = (int*)malloc(sizeof(int) * size);
return tmp;
}
void
add_velem(vect tmp, int elem) {
if(tmp->v_length != tmp->v_size) {
tmp->v_data[tmp->v_length] = elem;
tmp->v_length += 1;
} else {
tmp->v_size = tmp->v_size * 2;
tmp->v_length += 1;
int *new_vector = (int*)malloc(sizeof(int) * tmp->v_size);
memmove(new_vector, tmp->v_data, tmp->v_length); // GOT INPUT LIKE THIS:
// 500, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
// ALOT OF ZERO
/*
for(int i = 0; i < tmp->v_length; i++) {
new_vector[i] = tmp->v_data[i];
}*/ // BUT GOT RIGHT INPUT WHEN USING FOR. WHAT IS THE REASON?
free(tmp->v_data);
tmp->v_data = new_vector;
tmp->v_data[tmp->v_length - 1] = elem;
}
return;
}
int
get_vlength(vect tmp) {
return tmp->v_length;
}
int
get_vsize(vect tmp) {
return tmp->v_size;
}
int
get_velem(vect tmp, int elem) {
if(tmp->v_data == NULL) {
fprintf(stderr, "Index out of range!\n");
}else if(elem >= tmp->v_length) {
fprintf(stderr, "Index is out of range!\n");
return -1;
}
return tmp->v_data[elem];
}
void
delete_vector(vect tmp) {
free(tmp->v_data);
tmp->v_data = NULL;
free(tmp);
tmp = NULL;
}
int
main(void) {
vect example = new_vector(10);
printf("lenth of vector is %d\n", get_vlength(example));
add_velem(example, 500);
printf("element %d is pushed into vector\n", 500);
printf("size of vector is %d and\nlength of vector is %d\n", get_vsize(example), get_vlength(example));
int velem = get_velem(example, 0);
printf("elem 0 of vector is %d\n", velem);
for(int i = 1; i < 30; i++) {
add_velem(example, i);
}
printf("length of vector is %d now\n", get_vlength(example));
for(int i = 0; i < get_vlength(example); i++) {
printf("%d, ", get_velem(example, i));
}
delete_vector(example);
return 0;
}
I'm trying to pick up an image from my brand new window and then draw it back to the same window, just to train on XLib.
Here is my code :
#include<stdio.h>
#include<stdlib.h>
#include<stdint.h>
#include<X11/Xlib.h>
#include<X11/Xutil.h>
#include<sys/stat.h>
#include<sys/time.h>
#include<sys/types.h>
#include<unistd.h>
int main(int argc, char *argv[]) {
fd_set eventset;
fd_set zeroset;
// struct timeval timeout = {0, 0};
Display *display = 0;
int screen;
Window wnd;
XVisualInfo vinfo;
XSetWindowAttributes attr;
XEvent event;
XImage *bg;
Atom WM_message[2];
int run = 1;
FD_ZERO(&eventset);
FD_ZERO(&zeroset);
if(!(display = XOpenDisplay(0))) {
/* Display not found */
printf("Fail display.\n");
return 0;
}
screen = XDefaultScreen(display);
if(!XMatchVisualInfo(display, screen, 32, TrueColor, &vinfo)) {
if(!XMatchVisualInfo(display, screen, 24, TrueColor, &vinfo)) {
/* No proper color depth available */
XCloseDisplay(display); /* Close X communication */
printf("No found color display. Sorry.\n");
return 0;
}
}
attr.colormap = XCreateColormap(display, DefaultRootWindow(display), vinfo.visual, AllocNone);
attr.border_pixel = 0;
attr.background_pixel = 0x80000000;
attr.bit_gravity = NorthWestGravity;
attr.win_gravity = NorthWestGravity;
wnd = XCreateWindow(display, DefaultRootWindow(display), 0, 0, 300, 300, 0,
vinfo.depth, InputOutput, vinfo.visual,
CWColormap | CWBorderPixel | CWBackPixel | CWBitGravity | CWWinGravity, &attr);
/* Subscribe to window closing event */
WM_message[0] = XInternAtom(display, "WM_PROTOCOLS", 1);
WM_message[1] = XInternAtom(display, "WM_DELETE_WINDOW", 1);
XSetWMProtocols(display, wnd, WM_message, 2);
XFreeColormap(display, attr.colormap);
XSelectInput(display, wnd, ExposureMask | ButtonPressMask | KeyPressMask);
XMapWindow(display, wnd);
bg = XGetImage(display, XDefaultRootWindow(display), 0, 0, 300, 300, AllPlanes, ZPixmap);
// bg = XGetImage(display, wnd, 100, 100, 100, 100, AllPlanes, ZPixmap);
/* int x;
for(x = 0; x < 10000; x++) {
bg->data[x] = 0x80;
} */
XPutImage(display, wnd, XDefaultGC(display, screen), bg, 0, 0, 0, 0, 300, 300);
// XPutImage(display, wnd, XDefaultGC(display, screen), bg, 100, 100, 100, 100, 100, 100);
XMapWindow(display, wnd);
XFlush(display);
while(run) {
XNextEvent(display, &event);
switch(event.type) {
case Expose:
printf("w = %d, h = %d\n", event.xexpose.width, event.xexpose.height);
break;
case DestroyNotify:
run = 0;
break;
case ClientMessage:
{
if(event.xclient.message_type == WM_message[0]) {
if(event.xclient.data.l[0] == WM_message[1]) {
run = 0;
}
}
}
default:;
}
}
XDestroyImage(bg);
XDestroyWindow(display, wnd);
XCloseDisplay(display);
return 0;
}
This crash my program either on porteus and mobaxterm.
But this lines:
// bg = XGetImage(display, wnd, 100, 100, 100, 100, AllPlanes, ZPixmap);
/* int x;
for(x = 0; x < 10000; x++) {
bg->data[x] = 0x80;
} */
// XPutImage(display, wnd, XDefaultGC(display, screen), bg, 100, 100, 100, 100, 100, 100);
Doesn't crash my program... it just render nothing.
Can someone help me understand why do I experiment this weird behavior of X?
This is the error message I am getting:
X Error of failed request: BadMatch (invalid parameter attributes)
Major opcode of failed request: 72 (X_PutImage) Serial number of
failed request: 16 Current serial number in output stream: 18
After further reasearches and tries, I finnally found 2 facts :
First my post is mistaken :
this doesn't crash :
XPutImage(display, XDefaultRootWindow(display), XDefaultGC(display, screen), bg, 100, 100, 100, 100, 100, 100);
Those lines crash :
XPutImage(display, wnd, XDefaultGC(display, screen), bg, 0, 0, 0, 0, 300, 300);
XPutImage(display, wnd, XDefaultGC(display, screen), bg, 100, 100, 100, 100, 100, 100);
Second :
Writing on root window with default gc is alright because default gc is a gc corresponding to the default root window.
But using this GC for my own window is an error since I used color depth that can differ from root window.
So I have now this running well:
#include<stdio.h>
#include<stdlib.h>
#include<stdint.h>
#include<X11/Xlib.h>
#include<X11/Xutil.h>
#include<sys/stat.h>
#include<sys/time.h>
#include<sys/types.h>
#include<unistd.h>
int main(int argc, char *argv[]) {
fd_set eventset;
fd_set zeroset;
// struct timeval timeout = {0, 0};
Display *display = 0;
int screen;
Window wnd;
XVisualInfo vinfo;
XSetWindowAttributes attr;
XEvent event;
XImage *bg;
GC mainGC;
Atom WM_message[2];
int run = 1;
FD_ZERO(&eventset);
FD_ZERO(&zeroset);
if(!(display = XOpenDisplay(0))) {
/* Display not found */
printf("Fail display.\n");
return 0;
}
screen = XDefaultScreen(display);
if(!XMatchVisualInfo(display, screen, 32, TrueColor, &vinfo)) {
if(!XMatchVisualInfo(display, screen, 24, TrueColor, &vinfo)) {
/* No proper color depth available */
XCloseDisplay(display); /* Close X communication */
printf("No found color display. Sorry.\n");
return 0;
}
}
attr.colormap = XCreateColormap(display, DefaultRootWindow(display), vinfo.visual, AllocNone);
attr.border_pixel = 0;
attr.background_pixel = 0x80000000;
attr.bit_gravity = NorthWestGravity;
attr.win_gravity = NorthWestGravity;
wnd = XCreateWindow(display, DefaultRootWindow(display), 0, 0, 300, 300, 0,
vinfo.depth, InputOutput, vinfo.visual,
CWColormap | CWBorderPixel | CWBackPixel | CWBitGravity | CWWinGravity, &attr);
/* Subscribe to window closing event */
WM_message[0] = XInternAtom(display, "WM_PROTOCOLS", 1);
WM_message[1] = XInternAtom(display, "WM_DELETE_WINDOW", 1);
XSetWMProtocols(display, wnd, WM_message, 2);
XFreeColormap(display, attr.colormap);
XSelectInput(display, wnd, ExposureMask | ButtonPressMask | KeyPressMask);
XMapWindow(display, wnd);
XFlush(display);
mainGC = XCreateGC(display, wnd, 0, 0);
bg = XGetImage(display, wnd, 0, 0, 100, 100, AllPlanes, ZPixmap);
int x;
for(x = 0; x < 10000; x++) {
bg->data[x] = 0x80;
}
XPutImage(display, wnd, mainGC, bg, 0, 0, 100, 100, 100, 100);
while(run) {
XNextEvent(display, &event);
switch(event.type) {
case Expose:
printf("w = %d, h = %d\n", event.xexpose.width, event.xexpose.height);
break;
case DestroyNotify:
run = 0;
break;
case ClientMessage:
{
if(event.xclient.message_type == WM_message[0]) {
if(event.xclient.data.l[0] == WM_message[1]) {
run = 0;
}
}
}
default:;
}
}
XDestroyImage(bg);
XDestroyWindow(display, wnd);
XCloseDisplay(display);
return 0;
}
I've created XImage using XCreateImage and use XPutImage to display it on window, but XPutImage shows this picture only on second call of it. Why this happens?
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
void draw(char *rgb_out, int w, int h)
{
int i = 0;
for (i = 0;i < w*h;i += 4) {
rgb_out[i + 1] = 0;
rgb_out[i + 2] = 0;
rgb_out[i + 3] = 0;
}
return;
}
XImage *create_ximage(Display *display, Visual *visual, int width, int height)
{
char *image32 = (char *)malloc(width * height * 4);
draw(image32, width, height);
return XCreateImage(display, visual, 24,
ZPixmap, 0, image32,
width, height, 32, 0);
}
int main(int argc, char **argv)
{
int win_b_color;
int win_w_color;
XEvent xev;
Window window;
GC gc;
Display *display = XOpenDisplay(NULL);
Visual *visual;
XImage *ximage;
win_b_color = BlackPixel(display, DefaultScreen(display));
win_w_color = BlackPixel(display, DefaultScreen(display));
window = XCreateSimpleWindow(display,
DefaultRootWindow(display),
0, 0, 600, 400, 0,
win_b_color, win_w_color);
gc = XCreateGC(display, window, 0, NULL);
visual = DefaultVisual(display, 0);
XMapWindow(display, window);
XFlush(display);
ximage = create_ximage(display, visual, 100, 100);
while (1) {
int r;
r = XPutImage(display, window,
gc, ximage, 0, 0, 0, 0,
100, 100);
printf("RES: %i\n", r);
XSync(display, 1);
XFlush(display);
getchar();
}
return 0;
}
The trick is to wait that the windows is mapped. You can do this by Expose event.
int main(int argc, char **argv)
{
int win_b_color;
int win_w_color;
XEvent xev;
Window window;
GC gc;
Display *display = XOpenDisplay(NULL);
Visual *visual;
XImage *ximage;
win_b_color = BlackPixel(display, DefaultScreen(display));
win_w_color = BlackPixel(display, DefaultScreen(display));
window = XCreateSimpleWindow(display,
DefaultRootWindow(display),
0, 0, 600, 400, 0,
win_b_color, win_w_color);
visual = DefaultVisual(display, 0);
XSelectInput(display, window, ExposureMask | KeyPressMask);
XMapWindow(display, window);
XFlush(display);
gc = XCreateGC(display, window, 0, NULL);
ximage = create_ximage(display, visual, 100, 100);
XEvent event;
bool exit = false;
while (!exit) {
int r;
XNextEvent(display, &event);
if (event.type == Expose)
{
r = XPutImage(display, window,
gc, ximage, 0, 0, 0, 0,
100, 100);
printf("RES: %i\n", r);
}
else if (event.type == KeyPress)
exit = true;
}
return 0;
}
I am trying to learn lua and I seem to be stuck here.
For some reason the following code doesn't actually run the lua file.
int main()
{
lua_State* L = luaL_newstate();
luaL_openlibs(L);
int width = 0;
int height = 0;
if(!luaL_loadfile(L, "./src/luaconf.lua") || !lua_pcall(L, 0, 0, 0))
{
lua_getglobal(L, "width");
lua_getglobal(L, "height");
if(!lua_isnumber(L, -2))
{
luaL_error(L, "width isn't a number");
}
else
{
width = lua_tointeger(L, -2);
}
if(!lua_isnumber(L, -1))
{
luaL_error(L, "height isn't a number");
}
else
{
height = lua_tointeger(L, -1);
}
}
printf("%i x %i", width, height);
return 0;
}
I know that if I change if(!luaL_loadfile(L, "./src/luaconf.lua") || !lua_pcall(L, 0, 0, 0) to if(luaL_dofile(L, "./src/luaconf.lua")) it would work but I want to know why the above code doesn't work.
Shouldn't lua_pcall run the lua code? If not why not?
luaconf.lua
width = 500
height = 40
Note that in the code:
if(!luaL_loadfile(L, "./src/luaconf.lua") || !lua_pcall(L, 0, 0, 0))
if luaL_loadfile succeeds, it returns LUA_OK which has the value of 0, so the left operand of || evaluates as 1, according to short circuit, lua_pcall won't be executed.
So what you want is probably:
if ((luaL_loadfile(L, "./src/luaconf.lua") || lua_pcall(L, 0, 0, 0))
{
//error handle
}
else
{
//normal handle
}