Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added examples/textures_sprite_anim.c #36

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 125 additions & 0 deletions examples/textures_sprite_anim.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/*******************************************************************************************
*
* raylib [textures] example - Sprite animation
*
* Example originally created with raylib 1.3, last time updated with raylib 1.3
*
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
* BSD-like license that allows static linking with closed source software
*
* Copyright (c) 2014-2024 Ramon Santamaria (@raysan5)
*
********************************************************************************************/

#include "raylib.h"

void raylib_js_set_entry(void (*entry)(void));

#define MAX_FRAME_SPEED 15
#define MIN_FRAME_SPEED 1
const int screenWidth = 800;
const int screenHeight = 450;

// NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required)
Texture2D scarfy;

Vector2 position;
Rectangle frameRec;
int currentFrame = 0;
int framesCounter = 0;
int framesSpeed = 8; // Number of spritesheet frames shown by second

void GameFrame()
{
// Update
//----------------------------------------------------------------------------------
framesCounter++;

if (framesCounter >= (60/framesSpeed))
{
framesCounter = 0;
currentFrame++;

if (currentFrame > 5) currentFrame = 0;

frameRec.x = (float)currentFrame*(float)scarfy.width/6;
}

// Control frames speed
if (IsKeyPressed(KEY_RIGHT)) framesSpeed++;
else if (IsKeyPressed(KEY_LEFT)) framesSpeed--;

if (framesSpeed > MAX_FRAME_SPEED) framesSpeed = MAX_FRAME_SPEED;
else if (framesSpeed < MIN_FRAME_SPEED) framesSpeed = MIN_FRAME_SPEED;
//----------------------------------------------------------------------------------

// Draw
//----------------------------------------------------------------------------------
BeginDrawing();

ClearBackground(RAYWHITE);

DrawTexture(scarfy, 15, 40, WHITE);
DrawRectangleLines(15, 40, scarfy.width, scarfy.height, LIME);
DrawRectangleLines(15 + (int)frameRec.x, 40 + (int)frameRec.y, (int)frameRec.width, (int)frameRec.height, RED);

DrawText("FRAME SPEED: ", 165, 210, 10, DARKGRAY);
DrawText(TextFormat("%02i FPS", framesSpeed), 575, 210, 10, DARKGRAY);
DrawText("PRESS RIGHT/LEFT KEYS to CHANGE SPEED!", 290, 240, 10, DARKGRAY);

for (int i = 0; i < MAX_FRAME_SPEED; i++)
{
if (i < framesSpeed) DrawRectangle(250 + 21*i, 205, 20, 20, RED);
DrawRectangleLines(250 + 21*i, 205, 20, 20, MAROON);
}

DrawTextureRec(scarfy, frameRec, position, WHITE); // Draw part of the texture

DrawText("(c) Scarfy sprite by Eiden Marsal", screenWidth - 200, screenHeight - 20, 10, GRAY);

EndDrawing();
//----------------------------------------------------------------------------------
}

//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
InitWindow(screenWidth, screenHeight, "raylib [texture] example - sprite anim");

// NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required)
scarfy = LoadTexture("resources/scarfy.png"); // Texture loading

position = (Vector2){ 350.0f, 280.0f };
frameRec = (Rectangle){ 0.0f, 0.0f, (float)scarfy.width/6, (float)scarfy.height };
currentFrame = 0;

framesCounter = 0;
framesSpeed = 8; // Number of spritesheet frames shown by second

SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------

#ifdef PLATFORM_WEB
raylib_js_set_entry(GameFrame);
#else
// Main game loop
while (!WindowShouldClose())
{
GameFrame();
}

// De-Initialization
//--------------------------------------------------------------------------------------
UnloadTexture(scarfy); // Texture unloading


CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
#endif

return 0;
}
2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@
"core": ["core_basic_window", "core_basic_screen_manager", "core_input_keys", "core_input_mouse_wheel",],
"shapes": ["shapes_colors_palette"],
"text": ["text_writing_anim"],
"textures": ["textures_logo_raylib"],
"textures": ["textures_logo_raylib","texture_sprite_anim"],
}
const defaultWasm = Object.values(wasmPaths)[0][0];

Expand Down
39 changes: 33 additions & 6 deletions raylib.js
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,15 @@ class RaylibJs {
this.ctx.fillStyle = color;
this.ctx.fillRect(x, y, w, h);
}

DrawRectangleLines(x, y, w, h, color_ptr) {
const buffer = this.wasm.instance.exports.memory.buffer;
const color = getColorFromMemory(buffer, color_ptr);
const lineThick = 2;
this.ctx.strokeStyle = color;
this.ctx.lineWidth = lineThick;
this.ctx.strokeRect(x + lineThick/2, y + lineThick/2, w - lineThick, h - lineThick);
}

DrawRectangleLinesEx(rec_ptr, lineThick, color_ptr) {
const buffer = this.wasm.instance.exports.memory.buffer;
const [x, y, w, h] = new Float32Array(buffer, rec_ptr, 4);
Expand Down Expand Up @@ -285,15 +293,22 @@ class RaylibJs {
const buffer = this.wasm.instance.exports.memory.buffer;
const filename = cstr_by_ptr(buffer, filename_ptr);

var result = new Uint32Array(buffer, result_ptr, 5)
var img = new Image();
const result = new Uint32Array(buffer, result_ptr, 5)
const img = new Image();
img.src = filename;

//wait for the image to load, busy loop no idea what the correct solution would be
let maxWait = 1000;
while(maxWait >= 0)
maxWait--;
Comment on lines +301 to +303
Copy link
Contributor

@jkisor jkisor Feb 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tricky -- I think I found a way without waiting. #37
EDIT: Well, this example uses width/height data returned from LoadTexture -- which is yet to be implemented.

Copy link
Author

@IRooc IRooc Feb 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only synchronous option is the deprecated XMLHttpRequest one

function getImageDimensions(url) {
    let xhr = new XMLHttpRequest();
    xhr.overrideMimeType('text/plain; charset=x-user-defined'); //needed to not have unicode just ascii for the header part
    xhr.open('GET', url, false); // False for synchronous request
    xhr.send();
    
    if (xhr.status !== 200) {
        throw new Error('Failed to fetch image: ' + xhr.status);
    }
    
    let data = xhr.responseText;
    if (data.substr(1, 3) === 'PNG') {    
        let ihdr = data.indexOf('IHDR');
        if (ihdr === -1) {
            throw new Error('IHDR chunk not found');
        }
        var uint8 = Uint8Array.from(data.split("").map(x => x.charCodeAt()))
        let width = uint8[ihdr + 4] << 24 | uint8[ihdr + 5] << 16 | uint8[ihdr + 6] << 8 | uint8[ihdr + 7];
        let height = uint8[ihdr + 8] << 24 | uint8[ihdr + 9] << 16 | uint8[ihdr + 10] << 8 | uint8[ihdr + 11];
        return { width, height };
    }
    throw new Error('Not a supported image');
}


console.log("image loaded", filename, img.width, img.height);
this.images.push(img);

result[0] = this.images.indexOf(img);
// TODO: get the true width and height of the image
result[1] = 256; // width
result[2] = 256; // height
// TODO: get the true width and height of the image because it sometimes isnt loaded yet a refresh helps because it's cached
result[1] = img.width || 256; // width
result[2] = img.height || 256; // height
result[3] = 1; // mipmaps
result[4] = 7; // format PIXELFORMAT_UNCOMPRESSED_R8G8B8A8

Expand All @@ -309,6 +324,18 @@ class RaylibJs {

this.ctx.drawImage(this.images[id], posX, posY);
}
//void DrawTextureRec(Texture2D texture, Rectangle source, Vector2 position, Color tint)
DrawTextureRec(texture_ptr, rec_ptr, position_ptr, color_ptr) {
const buffer = this.wasm.instance.exports.memory.buffer;
const [id, width, height, mipmaps, format] = new Uint32Array(buffer, texture_ptr, 5);
const [x, y, w, h] = new Float32Array(buffer, rec_ptr, 4);
const [px, py] = new Float32Array(buffer, position_ptr, 2);
// // TODO: implement tinting for DrawTexture
// const tint = getColorFromMemory(buffer, color_ptr);

this.ctx.drawImage(this.images[id], x, y, w, h, px, py, w, h);

}

// TODO: codepoints are not implemented
LoadFontEx(result_ptr, fileName_ptr/*, fontSize, codepoints, codepointCount*/) {
Expand Down
Binary file added resources/scarfy.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.