Page 1 of 1

C: Affichage de sprites incorrect

Unread postPosted: 04 Oct 2024, 18:25
by elyas.creates
Salut! Dans mon code, la rocket s'affiche avec une partie du joueur (alors que j'ai affiché uniquement la rocket) quand l'image de la rocket pointait vers la gauche. Quand l'image pointait vers le haut (l'image d'origine modifiée), seulement la partie haute de la rocket s'affichait...
Pour info, la rocket a une taille de 14x26 (dans l'image d'origine, quand la rocket est allongée) et quand j'ai modifié l'image d'origine pour qu'elle soit debout, ca affichait seulement les 14 premières lignes de l'image.
Voici le code:
Code: Select all
#include <keypadc.h>
#include <graphx.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <debug.h>
#include <tice.h>
/* Include the converted graphics file */
#include "gfx/gfx.h"

/* Include the external tilemap data */
extern unsigned char tilemap_map[];

/* Tilemap defines */
#define TILE_WIDTH          16
#define TILE_HEIGHT         16

#define TILEMAP_WIDTH       20
#define TILEMAP_HEIGHT      15

#define TILEMAP_DRAW_WIDTH  20
#define TILEMAP_DRAW_HEIGHT 15

#define Y_OFFSET            0 // CAMERA_X
#define X_OFFSET            0 // CAMERA_Y

#define SPEED               2
#define DIAGONAL_SPEED      (SPEED * 0.707) // Speed reduction for diagonal movement
typedef struct {
    int x, y;
    float dx, dy;
    bool active;
} Rocket;

/* Constants */
#define MAX_ROCKETS 10
#define ROCKET_SPEED 2.5
#define COOLDOWN_TIME 30  // 0.5 seconds as RTC counts at 60Hz

/* Rocket list */
Rocket rockets[MAX_ROCKETS] = {0};
int rocket_cooldown = 0; 

/* Function to add a new rocket */
void add_rocket(int start_x, int start_y) {
    for (int i = 0; i < MAX_ROCKETS; i++) {
        if (!rockets[i].active) {
            rockets[i].x = start_x;
            rockets[i].y = start_y;
            float angle = atan2f(0 - start_y, 0 - start_x);  // Calculate angle towards (0,0)
            rockets[i].dx = ROCKET_SPEED * cosf(angle);
            rockets[i].dy = ROCKET_SPEED * sinf(angle);
            rockets[i].active = true;
            rocket_cooldown = COOLDOWN_TIME;  // Start cooldown
            break;
        }
    }
}

/* Function to update rockets */
void update_rockets(gfx_tilemap_t *tilemap) {
    for (int i = 0; i < MAX_ROCKETS; i++) {
        if (rockets[i].active) {
            rockets[i].x += rockets[i].dx;
            rockets[i].y += rockets[i].dy;

            // Check for collisions with map boundaries or tiles 1, 2, 6
            unsigned int tile_x = rockets[i].x / TILE_WIDTH;
            unsigned int tile_y = rockets[i].y / TILE_HEIGHT;

            if (rockets[i].x < 0 || rockets[i].y < 0 ||
                rockets[i].x >= TILEMAP_WIDTH * TILE_WIDTH || rockets[i].y >= TILEMAP_HEIGHT * TILE_HEIGHT ||
                *gfx_TilePtrMapped(tilemap, tile_x, tile_y) == 1 ||
                *gfx_TilePtrMapped(tilemap, tile_x, tile_y) == 2 ||
                *gfx_TilePtrMapped(tilemap, tile_x, tile_y) == 6) {
                rockets[i].active = false;  // Deactivate rocket on collision
            }
        }
    }
}

/* Function to draw rockets */
void draw_rockets(void) {
    for (int i = 0; i < MAX_ROCKETS; i++) {
        if (rockets[i].active) {
            int angle = atan2f(0 - rockets[i].y, 0 - rockets[i].x) * 128 / M_PI;  // Convert angle to gfx 256 position
            gfx_RotatedScaledTransparentSprite_NoClip(rocket, rockets[i].x, rockets[i].y, angle, 64);
        }
    }
}

/* Function to check if a tile is walkable (0 is walkable, 1/2/6 are obstacles) */
bool is_walkable(unsigned int tile_x, unsigned int tile_y, gfx_tilemap_t *tilemap) {
    if (tile_x < 0 || tile_x >= TILEMAP_WIDTH || tile_y < 0 || tile_y >= TILEMAP_HEIGHT) {
        return false; // Out of bounds
    }
    uint8_t block_mapped = *gfx_TilePtrMapped(tilemap, tile_x, tile_y);
    return !(block_mapped == 1 || block_mapped == 2 || block_mapped == 6);
}

int main(void)
{
    unsigned int x_offset = 0;
    unsigned int y_offset = 0;
    gfx_tilemap_t tilemap;

    /* Initialize the tilemap structure */
    tilemap.map         = tilemap_map;
    tilemap.tiles       = tileset_tiles;
    tilemap.type_width  = gfx_tile_16_pixel;
    tilemap.type_height = gfx_tile_16_pixel;
    tilemap.tile_height = TILE_HEIGHT;
    tilemap.tile_width  = TILE_WIDTH;
    tilemap.draw_height = TILEMAP_DRAW_HEIGHT;
    tilemap.draw_width  = TILEMAP_DRAW_WIDTH;
    tilemap.height      = TILEMAP_HEIGHT;
    tilemap.width       = TILEMAP_WIDTH;
    tilemap.y_loc       = Y_OFFSET;
    tilemap.x_loc       = X_OFFSET;

    unsigned int player_x = TILEMAP_DRAW_WIDTH * TILE_WIDTH / 2;
    unsigned int player_y = TILEMAP_DRAW_HEIGHT * TILE_HEIGHT / 2 + 8;

    /* Buffers for flipping sprites */
    gfx_sprite_t *flipped_side = gfx_MallocSprite(15, 20); // Allocate memory for the flipped sprite
    gfx_sprite_t *player_sprite = brock_down; // Default sprite (down)

    /* Initialize graphics drawing */
    gfx_Begin();

    /* Set the palette */
    gfx_SetPalette(global_palette, sizeof_global_palette, 0);
    gfx_SetColor(0);
    gfx_SetTextFGColor(1);
    gfx_SetTextBGColor(0);

    /* Draw to buffer to avoid tearing */
    gfx_SetDrawBuffer();

    /* Set monospace font with width of 8 */
    gfx_SetMonospaceFont(8);

    gfx_SetTransparentColor(0);

    /* Wait for the enter key to quit */
    do
    {
        kb_key_t arrows;
        kb_key_t keys;
        /* Scan the keypad */
        kb_Scan();
        arrows = kb_Data[7];  // Check arrow keys (7th row of kb_Data)
        keys = kb_Data[1];
        /* Handle key presses to move the tilemap */
        bool moved = false;
        float move_x = 0, move_y = 0;

        /* Check directional inputs and update player sprite */
        if (arrows & kb_Down) {
            move_y += SPEED;
            player_sprite = brock_down;  // Change sprite to down
        }
        if (arrows & kb_Up) {
            move_y -= SPEED;
            player_sprite = brock_up;  // Change sprite to up
        }
        if (arrows & kb_Right) {
            move_x += SPEED;
            player_sprite = brock_side;  // Change sprite to right
        }
        if (arrows & kb_Left) {
            move_x -= SPEED;
            gfx_FlipSpriteY(brock_side, flipped_side);  // Flip sprite for left movement
            player_sprite = flipped_side;  // Set flipped sprite for left direction
        }

        /* If moving diagonally, normalize speed */
        if (move_x != 0 && move_y != 0) {
            move_x *= DIAGONAL_SPEED / SPEED;
            move_y *= DIAGONAL_SPEED / SPEED;
        }

        /* Calculate the new positions */
        unsigned int new_player_x = player_x + (int)move_x;
        unsigned int new_player_y = player_y + (int)move_y;

        /* Check if the movement is valid (collision detection) */
        if (move_y > 0) { // Moving down
            unsigned int tile_y = (new_player_y + 15) / TILE_HEIGHT;  // bottom side
            unsigned int tile_x_left = player_x / TILE_WIDTH;  // bottom-left corner
            unsigned int tile_x_right = (player_x + 15) / TILE_WIDTH;  // bottom-right corner
            if (is_walkable(tile_x_left, tile_y, &tilemap) && is_walkable(tile_x_right, tile_y, &tilemap)) {
                player_y = new_player_y;
                moved = true;
            }
        } else if (move_y < 0) { // Moving up
            unsigned int tile_y = new_player_y / TILE_HEIGHT;  // top side
            unsigned int tile_x_left = player_x / TILE_WIDTH;  // top-left corner
            unsigned int tile_x_right = (player_x + 15) / TILE_WIDTH;  // top-right corner
            if (is_walkable(tile_x_left, tile_y, &tilemap) && is_walkable(tile_x_right, tile_y, &tilemap)) {
                player_y = new_player_y;
                moved = true;
            }
        }

        if (move_x > 0) { // Moving right
            unsigned int tile_x = (new_player_x + 15) / TILE_WIDTH;  // right side
            unsigned int tile_y_top = player_y / TILE_HEIGHT;  // top-right corner
            unsigned int tile_y_bottom = (player_y + 15) / TILE_HEIGHT;  // bottom-right corner
            if (is_walkable(tile_x, tile_y_top, &tilemap) && is_walkable(tile_x, tile_y_bottom, &tilemap)) {
                player_x = new_player_x;
                moved = true;
            }
        } else if (move_x < 0) { // Moving left
            unsigned int tile_x = new_player_x / TILE_WIDTH;  // left side
            unsigned int tile_y_top = player_y / TILE_HEIGHT;  // top-left corner
            unsigned int tile_y_bottom = (player_y + 15) / TILE_HEIGHT;  // bottom-left corner
            if (is_walkable(tile_x, tile_y_top, &tilemap) && is_walkable(tile_x, tile_y_bottom, &tilemap)) {
                player_x = new_player_x;
                moved = true;
            }
        }

        if (keys & kb_2nd && rocket_cooldown == 0) {
            add_rocket(player_x, player_y);
        }
        /* Update cooldown */
        if (rocket_cooldown > 0) {
            rocket_cooldown--;
        }
        update_rockets(&tilemap);
        /* Draw tilemap first */
        gfx_Tilemap_NoClip(&tilemap, x_offset, y_offset);
       
        /* Draw player sprite */
        gfx_TransparentSprite(player_sprite, player_x, player_y - 4);
        draw_rockets();
        /* Swap draw buffer to update the screen */
        gfx_SwapDraw();

    } while (kb_Data[6] != kb_Annul);  // Exit on Annul key (6th row of kb_Data)



    /* End graphics drawing */
    gfx_End();

    return 0;
}

Re: C: Affichage de sprites incorrect

Unread postPosted: 04 Oct 2024, 20:26
by critor
Coucou.

Je t'avais répondu sur le chat.

Difficile d'être sûr sans la totalité du code pour tester.
Mais j'ai une hypothèse, peut-être fausse, ça ressemble à un affichage de tes données de sprites définies en 8 bits, alors que l'écran aurait été laissé en 16 bits.

Re: C: Affichage de sprites incorrect

Unread postPosted: 04 Oct 2024, 20:28
by Adriweb
@critor : apparemment non, puisque gfx_Begin() est bien present au debut (et le end a la fin).

Si tu fais make clean puis make gfx puis make all, c'est toujours pareil ?
Ton fichier convimg.yaml contient quoi ?

Mais en effet, si tu peux joindre ton projet en entier (dans une archive zip par exemple), ca sera plus pratique pour te repondre.