🤑 Indie game store🙌 Free games😂 Fun games😨 Horror games
👷 Game development🎨 Assets📚 Comics
🎉 Sales🎁 Bundles

Draw Sprite Demo v2.0

A topic by allaze-eroler created 168 days ago Views: 390 Replies: 4
Viewing posts 1 to 4

hello folks, after many test with the draw sprite demo, i wasn't able to make it work so, i decided to share it:

first, the code source:

--
-- Copyright (c) 2017, Jesse Freeman. All rights reserved.
--
-- Licensed under the Microsoft Public License (MS-PL) License.
-- See LICENSE file in the project root for full license information.
--
-- Contributors
-- --------------------------------------------------------
-- This is the official list of Pixel Vision 8 contributors:
--
-- Jesse Freeman - @JesseFreeman
-- Christer Kaitila - @McFunkypants
-- Pedro Medeiros - @saint11
-- Shawn Rakowski - @shwany
--

-- These values represent the shell's position, speed, animation
-- time and frame.
local shellAPos = {x = 0, y = 8*8}
local shellBPos = {x = 8*22, y = 0}

-- This 2D array stores sprite IDs for the turtle shell animations.
-- Each shell is a made up of 4 sprites in a 2x2 grid.
--local shellSprites = {{0,0,2,2},{1,1,3,3}}

local shellSprites =
    {
        {0,0,flipH,2,2,flipH},{1,1,flipH,3,3,flipH}
    }



local speed = 100

local time = 0
local frame = 1

-- The Init() method is part of the game's lifecycle and called a game
-- starts. We are going to use this method to configure the DisplayChip,
-- ScreenBufferChip and also draw fonts into the background layer.
function Init()

    -- Here we are starting by changing the background color and telling
    -- the DisplayChip to wrap.
    apiBridge:ChangeBackgroundColor(32)
    apiBridge:ToggleDisplayWrap(true)

    -- Here we are rebuilding the screen buffer so we can draw tile and
    -- fonts to it. This will cut down on our draw calls.
    apiBridge:RebuildScreenBuffer()

    -- With the ScreenBuffer ready, we can now draw fonts into it. Here
    -- we are creating two new labels to display under our demo sprites.
    apiBridge:DrawFontToBuffer("Sprite Test", 1, 1, "large-font", 0)
    apiBridge:DrawFontToBuffer("Position Wrap Test", 1, 6, "large-font", 0)

end

-- The Update() method is part of the game's life cycle. The engine
-- calls Update() on every frame before the Draw() method. It accepts
-- one argument, timeDelta, which is the difference in milliseconds
-- since the last frame. We are going to keep track of time to sync
-- up our sprite animation as well as move the sprites across the screen.
function Update(timeDelta)

    -- We are going to move the sprite positions by calculating the speed by
    -- the timeDelata. We can then add this to the x or y position of our sprite
    -- vector.
    shellAPos.x = math.ceil(shellAPos.x + (speed * timeDelta))
    shellBPos.y = math.ceil(shellBPos.y + (speed * timeDelta))

    -- We are going to keep track of the time by adding timeDelta to our time
    -- field. We can then use this to tell if we should change our animation frame.
    time = time + timeDelta

    -- Here we'll determine when it's time to change the sprite frame.
    if(time > 0.09) then

        -- If time is past the frame we'll increase the frame number to advance the animation.
        frame = frame + 1

        -- We need to reset the frame number if it is greater than the number of frames.
        if(frame > #shellSprites) then
            frame = 1
        end

        -- Now we can reset time back to 0 to start tracking the next frame change.
        time = 0

    end

end

-- The Draw() method is part of the game's life cycle. It is called after Update() and
-- is where all of our draw calls should go. We'll be using this to render each of
-- the sprites and font characters to the display.
function Draw()

    -- It's important to clear the display on each frame. There are two ways to do this. Here
    -- we are going to use the DrawScreenBuffer() way to copy over the existing buffer and clear
    -- all of the previous pixel data.
    apiBridge:DrawScreenBuffer()

    -- Here we are going to draw the first example. The turtle shell is made up of 4 sprites.
    -- We'll draw each sprite out with a few pixels between them so you can see how they are
    -- put together.
    apiBridge:DrawSprite(0, 8, 24, false, false, true, 0)
    apiBridge:DrawSprite(0, 18, 24, true, false, true, 0)
    apiBridge:DrawSprite(2, 8, 34, false, false, true, 0)
    apiBridge:DrawSprite(2, 18, 34, true, false, true, 0)

    -- For the next two examples we'll use the DrawSprites() method
    -- which allows us to combine sprites together into a single draw request.
    -- Each sprite still counts as a draw call but this simplifies drawing
    -- larger sprites in your game.
    apiBridge:DrawSprites(shellSprites[1], 32, 24, 2, false, false, true, 0)
    --apiBridge:DrawSprites(shellSprites[frame], 54, 24, 2, false, false, true, 0)

    -- Here we are drawing a turtle shell along the x and y axis. We'll take advantage of the Display's wrap
    -- setting so that the turtle will appear on the opposite side of the screen even when the x or y
    -- position is out of bounds.
    --apiBridge:DrawSprites(shellSprites[frame], shellAPos.x, shellAPos.y, 2, false, false, true, 0)
    apiBridge:DrawFont("("..shellAPos.x..","..shellAPos.y..")", shellAPos.x, shellAPos.y + 20, "large-font", 0)

    -- The last thing we are going to do is draw text below each of our moving turtles so we can see the
    -- x and y position as they wrap around the display.
    --apiBridge:DrawSprites(shellSprites[frame], shellBPos.x, shellBPos.y, 2, false, false, true, 0)
    apiBridge:DrawFont("("..shellBPos.x..","..shellBPos.y..")", shellBPos.x, shellBPos.y + 20, "large-font", 0)

end
    

and the sprites i used for the coding part:



the idea is that we could display the shell with only one half of sprite and than mirroring it like the nes games actually does it. let take a look at that example i found from google:


as you may noticed, alot of sprite are only one half but can be mirrored thank to the coding part unfortunately, it's not pratical because it was in assembly language. so, that is why i'm trying to reproduce it in lua scripting because i know it might be possible but i haven't yet found how to do that. all i found as information is this:

https://nesdoug.com/2015/11/22/6-sprites/ as you see, many nes games used that trick to make it as a whole sprite by only using half, that is exactly what i'm trying to achieve. i don't know if the guy from nesdoug is using the lua scripting but it's clear that he found a way to do this way.

also, i found this interesting information about mirroring and flipping from nes dev:

https://wiki.nesdev.com/w/index.php/Mirroring and this: http://wiki.nesdev.com/w/index.php/PPU_OAM

if you have a better suggestion, feel free to share it!

So if I'm reading this correctly you want to use one side of the shell to make a complete graphic? The sprite draw method allows you to flip a sprite vertically or horizontally so you should be able to do this. The only caveat is that you won't be able to use the DrawSprites helper method which lays sprites out in a grid for you which makes treating larger graphics made up of multiple sprites as one object. So you would have to do each sprite by hand but you should be able to turn the 4 sprite shell into a 2 sprite shell using horizontal flipping but at the added expense of making 4 manual sprite draw calls.

To be honest, that level of optimization was mandatory on the Nes. Since PV8 can store a lot more sprites there really isn't a penalty for having a turtle shell that has unique sprites for each side. I'd say where you could optimize the most is by using the color offset value to simulate palette swapping and not use different sprites for each color of turtle shell.

I want to do some better demos that show off the power of the sprite drawing APIs. I'll try to focus on that after the next two release when I go back and clean up the tools.

So I posted this to twitter yesterday showing off a demo that tests out the new drawing APIs. Is this what you had in mind?

Here is a link to the tweet and what the final demo looks like.

hummmm yes that is what i had in mind, for now, i have to wait you release it so, i could test it out. since seeing like this, it's kind hard for me to imagine how is was going to work XD;;

ps: try to avoid jpg file because it cause lot of artifacts, use png or gif for pixel art :)

FYI you can do this now with the current APIs but the next version will have a much simplier API to use. I'll still support the old ones for a few releases so I don't break people's games.