Navigation

    Fuze Arena Logo
    • Register
    • Login
    • Search
    • Categories
    • Recent
    • Popular
    • Users
    • Groups
    • Help
    • Discord

    Finding it hard to get enemies

    Help
    5
    27
    1675
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • waldron
      waldron F last edited by

      This post is deleted!
      1 Reply Last reply Reply Quote 0
      • Dave
        Dave Fuze Team last edited by

        @waldron The gothicVania demo was written quite a while back and since then I've learned a good many things which make things easier. There will be an updated version of this demo at some point in the near future.

        You have two options. You either go down a sprite engine route, using functions such as setSpriteCamera(), createSprite(), setSpriteAnimation() and setSpriteLocation() for example. This requires doing things in a certain way and may or may not be the way you want to do things. Using sprites certainly makes a few things much easier to think about. I am working on a version of the gothicVania demo which uses the sprite engine and will serve as a good example of how to use the engine in a game context.

        The other way is to go the route of the Game tutorial series. This method is the one used in the gothicVania demo as it stands now. Using an array of tiles to draw a level, etc, along with commands like drawSheet() to draw and animate the sprite.

        In both routes, you benefit greatly from using a state machine so it's a very good idea to get that concept under your belt.

        Feel free to send me a private message to ask about any aspect at all - I'll do my very best to get you to the stage that you're happy with continuing the project.

        1 Reply Last reply Reply Quote 1
        • lawyerlounge
          lawyerlounge last edited by

          I can't wait to see a version in which the former method you mentioned is used. Its so fascinating that there are so many different approaches to game coding, and can't wait until I can fully grasp the benefits of each in different scenarios.

          1 Reply Last reply Reply Quote 3
          • Dave
            Dave Fuze Team last edited by

            @lawyerlounge

            It is fascinating. Especially when you look at older games and the specific approaches that needed to be taken due to restrictions/features in particular hardware.

            I wish I knew so much more and had a lot more knowledge under my belt. When I hear the Fuze Team's @Luke talk about the specific architectures of various systems and the trade-offs developers had to make in order to achieve certain things, it blows my mind.

            There's always more to learn, no matter what!

            The sprite engine version of the gothicVania demo will be done fairly soon.

            1 Reply Last reply Reply Quote 0
            • lawyerlounge
              lawyerlounge last edited by

              so basically if you go the route your calling "sprite engine" you would createSprite() and have updateSprite()/drawSprite() and setSpriteAnimation() whereas the other method (i guess "tile method") you are just load the entire sprite tile as an img and just need to drawSheet()?

              Is it that using the "sprite engine" you have a lot more options and control, yet you would need to be a lot more specific in different approaches (like collisions and background detection) than you would if you were just using drawSheet()? because it seems with the "tile method", you also would use an array for the level or background and collisions. So that whole approach would just not be compatible with the "sprite engine"?

              Forgive my way of asking a question before understanding enough i suppose, but I think once I can see your new example a lot of "pieces" will click into place and further my understanding of drawing sprites!

              Dave 1 Reply Last reply Reply Quote 1
              • Dave
                Dave Fuze Team @lawyerlounge last edited by Dave

                @lawyerlounge this is a great question.

                In terms of loading assets, there is no difference. You have to work with whatever the layout of the spritesheets are. For example, in Untied Games there are a lot of huge character spritesheets with lots of different animations in one place. In this case you have to load only a single spritesheet and you have access to all of the different animations.

                In the Ansimuz assets, most of his characters (actually all of them, I believe) are done as separate sheets for separate animation sets. One for idle, one for run, etc.

                Whether going down a sprite engine route or a draw commands route, you will need to load and structure your assets in a way which works with those specific assets. This isn't changed by which route you end up going down.

                You have the exact same amount of options and control no matter which method you use, it depends entirely on what you're most comfortable with and understand more. One big difference is the command setSpriteAnimation(). Using setSpriteAnimation(), you can provide it with a sprite, a start tile and an end tile, a number of frames per second, and it will loop that animation for you beautifully.

                Doing this without the sprite commands means using drawSheet() and "doing things yourself", so to speak. For example:

                sheet = loadImage( "file" )
                start = 0 // first tile in the animation sequence
                end = 7 // last tile in the animation sequence
                fps = 0.1 // frames per second
                
                loop
                    clear()
                    drawSheet( sheet, tile, {x, y, w, h} ) // draw the current tile from the spritesheet
                    tile += fps // increase the tile by our fps variable
                    if tile > end then // check if animation has reached the end of the sequence
                        tile = start // if so, reset the tile
                    endif
                    update()
                repeat
                

                The code above is essentially doing the same thing as:

                sheet = loadImage("file")
                sprite = createSprite()
                setSpriteImage( sprite, sheet )
                setSpriteAnimation( sprite, sheet, 0, 7, 10 ) // this one line is the same as the counter and if statement in the previous example
                
                loop
                    clear()
                    updateSprites()
                    drawSprites()
                    update()
                repeat
                

                The big difference is that when using the sprite commands (and especially when using a map which you've drawn in the map editor, with collision boxes), you also should be using the other sprite commands for your program. Map collision will only work properly with setSpriteCamera(), for example.

                You also run into specific problems to tackle depending on which method you're going for. setSpriteAnimation() is a super useful command, but if your code is written incorrectly it will not work. Take this example here:

                // assuming necessary sprite setup stuff here
                loop
                    clear()
                    j = controls(0)
                    if j.a then 
                        setSpriteAnimation( sprite, sheet, 10, 18, 10 ) // on A button press, set the sprite animation sequence to a range of tile 10 - 18 at 10 fps. This is purely an example, numbers are arbitrary
                    endif
                    update()
                repeat
                

                In this example, when you press the A button, setSpriteAnimation() will execute on every frame that A is held. This results in our characters not moving, being locked in the first frame of animation. To get around this you'll need "switches" or "flags" to stop the line from being read.

                When the updated gothicVania demo is in Fuze it will indeed answer a lot of these questions. I've gotten much better at writing this sort of code since that was made and I'm excited to get it in there.

                Furthermore, the ninjaScroller demo I'm working on currently uses the drawSheet() method only. With this, you'll have two fleshed-out examples using both methods and this will hopefully allow everyone to do what they find easiest to get their heads around!

                1 Reply Last reply Reply Quote 2
                • lawyerlounge
                  lawyerlounge last edited by

                  This explanation was brilliant and I appreciate you taking the time and showing the examples side by side as well as an example that you would "think" would work intuitively.. yet doesn't.

                  About the sprite engine as well:
                  I originally tried this route and I believe I reached a conclusion as to why the animation would't work for me. Due to everything needing to be within the "main loop", and that the main loop itself runs super quickly (is it 60 times a second??), that even though I had setSpriteAnimation(sprite, start, end, fps) what was happening was this was being called 60 times a second and sprite never had a chance to get to the second frame of the animation.

                  I notice in your example above, the setSpriteAnimation() is located above and outside of the main loop. It would be helpful to see a "simple" example of how you would call "setSA()" in the main loop within conditions and input tests/or just blatantly in the loop at all.

                  I appreciate the direct help and examples and I look forward to seeing your new demos when completed.

                  -MikeV

                  Dave 1 Reply Last reply Reply Quote 1
                  • Dave
                    Dave Fuze Team @lawyerlounge last edited by Dave

                    @lawyerlounge

                    Absolutely happy to. There is a way I could provide a very "simple" example, without using states etc, but in my opinion it honestly ends up being far more complicated.

                    Usually I begin with something like this:

                    spritesheet = loadImage("filename")
                    sprite = createSprite()
                    setSpriteImage( sprite, spritesheet )
                    
                    // Now we create an array of animation data. Each element of this array is an array of two elements, the start tile and the end tile. 
                    // Numbers are of course arbitrary.
                    playerAnimationData = [
                        [ 0, 6 ], // let's say this is the idle animation
                        [ 7, 20 ], // this one could be an attack animation
                        [ 21, 30 ] // this one could be jump
                    ]
                    
                    // Now we make state variables to use as indexes into that animation array:
                    idle = 0
                    attack = 1
                    jump = 2
                    
                    // Now the variable to store the current state
                    state = idle
                    
                    // We will also **need** to keep track of the player's **old state**, in order to tell when we change animation.
                    oldState = -1 // Making it -1 for now because we'll be setting it properly in the loop.
                    
                    // Lastly, a flag variable make sure that we only trigger the ``setSpriteAnimation()``` once
                    animSwitch = false
                    

                    Okay, with that done, we can have something like the following in our main loop:

                    loop
                        clear()
                        updateSprites()
                        j = controls(0)
                    
                        // It's extremely useful to know which frame of animation you character is on, so let's make a local variable for that:    
                        playerFrame = getSpriteAnimFrame( sprite )    
                    
                        // If A is pressed and the character was not previously in the jump state, enter jump state and set the animSwitch
                        if j.a and oldState != jump then
                            animSwitch = true
                            state = jump
                        endif
                    
                        // You might want your attack to only be possible if the player is not jumping, for instance:
                        if j.x and oldState != attack and oldState != jump then
                            animSwitch = true
                            state = attack
                        endif    
                    
                        // With the sprite's current animation frame known, we can also easily return to idle after certain animations:
                        if state == attack and playerFrame >= playerAnimationData[state][1] then
                            animSwitch = true
                            state = idle
                        endif
                    
                        // Notice that in our if statements, we simply need only change the state and turn the animation switch on. If we weren't using an array of animation data with a state machine,
                        // we would have to do separate ```setSpriteAnimation()``` calls for each if statement. This ends up being quite cluttered and not so simple when you've got a large scale project.
                        
                        // However, with this way of doing things, we simply need this one if statement at the end. We check if the current state is != oldState and if our switch is on:
                        if state != oldState and animSwitch then
                            // playerAnimationData[ state ][0] contains the start tile for the current state, playerAnimationData[ state ][1] is the end tile
                            setSpriteAnimation( sprite, playerAnimationData[ state ][0], playerAnimationData[ state ][1], 10 ) // 10 fps is arbitrary
                            animSwitch = false // turn the switch off
                        endif
                        
                        // Finally, we update the oldState variable to contain the current state at the end of the frame.
                        oldState = state
                        update()
                    repeat
                    

                    I might be missing a couple of small details here as I didn't want to overload, but this is the method I'm using in the updated gothic Vania demo and it works nicely. It also grants you a lot of control over which states happen when.

                    Actually, looking at this I'm not sure you actually need the animSwitch variable, since just knowing if the state is not equal to the old state might be enough. I would use it for good measure!

                    I really hope this is what you were looking for. Please let me know if I can elaborate on anything at all.

                    1 Reply Last reply Reply Quote 2
                    • lawyerlounge
                      lawyerlounge last edited by lawyerlounge

                      Thanks again for a great example. I noticed there was no use of drawSprites() in your loop. Is that possibly the reason I had issues with the animation not running?

                      image = loadImage("filename")
                      sprite = createSprite()
                      setSpriteImage( sprite, image)
                      
                      startFrame = 0
                      endFrame  = 10
                      fps = 10
                      
                      Loop
                            clear()
                          
                            setSpriteAnimation( sprite, startFrame, endFrame, fps)
                      
                            updateSprites()
                            drawSprites()
                      
                            update()
                      repeat
                      

                      I remember just trying to get the animation to work anywhere inside the loop (without any states or conditions) resulted in no movement at all. Is it because I was misusing some sort of update() command or drawSprites() command, and it kept redrawing the initial start frame and not allowing the animation to count up to 10 at 10 fps? I'm at work and away from my switch, but I believe I tried almost all combinations of including/excluding any update() draweSprites() and updateSprites() to no avail.

                      Does that make sense though?

                      pianofire 1 Reply Last reply Reply Quote 0
                      • pianofire
                        pianofire Fuze Team @lawyerlounge last edited by pianofire

                        @lawyerlounge setSpriteAnimation() initializes the animation. If you call it in your game loop it will keep resetting it back to the beginning. The updateSprites() call is the one that will move the animation forward. drawSprites() will actually draw them into video memory and update() will render that to the screen.

                        So this should work (let me know if it doesn't). You also need to set the sprite location using setSpriteLocation

                        sprite = createSprite()
                        setSpriteImage( sprite, image)
                        setSpriteLocation(sprite, gwidth()/2, gheight()/2)
                        startFrame = 0
                        endFrame  = 10
                        fps = 10
                        setSpriteAnimation( sprite, startFrame, endFrame, fps)
                        
                        Loop
                              clear()
                            
                        
                              updateSprites()
                              drawSprites()
                        
                              update()
                        repeat
                        
                        1 Reply Last reply Reply Quote 0
                        • Jonboy
                          Jonboy Fuze Team last edited by

                          Ha Waldron... "Finding it hard to get enemies".. I make new ones every day!

                          Sorry.. can't be much more help than that at the moment. See what I mean.

                          waldron 1 Reply Last reply Reply Quote 0
                          • lawyerlounge
                            lawyerlounge last edited by

                            What is the main difference from Dave's example (2 posts up) and my example (which both at some point have the setSpriteAnimation() function inside of the main loop) that would cause his to work and mine not to.

                            Other than having "if statements" (which basically change a variable called "state" which in turn changes the startFrame and endFrame vars for the arguments within setSpriteAnimation), and providing a check to see if the current state is not what it used to be, what causes the program in Dave's post to let the animation run from start to finish without constantly executing the beginning of the animation? (the problem you dissected within my example)

                            Or is the method of checking if state != oldState required, because if you intend an animation to change throughout the main loop you need to find a way to only run it once at particular moments? And for any asset that doesn't need to change animations you would just use the setSpriteAnimation function before the main loop and set the visibility to false until needing to display?

                            I think I've figured out the bare requirements for using sSA() in the loop... would this work?

                            sprite = createSprite()
                            setSpriteImage( sprite, image)
                            setSpriteLocation(sprite, gwidth()/2, gheight()/2)
                            startFrame = 0
                            endFrame  = 10
                            fps = 10
                            
                            animSwitch = true
                            
                            Loop
                                  clear()
                                 
                                  currentFrame = getSpriteAnimFrame( sprite )
                            
                                  if animSwitch then
                                        setSpriteAnimation( sprite, startFrame, endFrame, fps)
                                        animSwitch = false
                                  endif
                            
                                  if currentFrame >= endFrame then
                                        animSwitch = true
                                  endif
                            
                                  updateSprites()
                                  drawSprites()
                            
                                  update()
                            repeat
                            

                            P.S. thank you for all of the help teaching me something that must be simple for you guys!
                            -MikeV

                            pianofire 1 Reply Last reply Reply Quote 0
                            • pianofire
                              pianofire Fuze Team @lawyerlounge last edited by

                              @lawyerlounge Not at all. That's what we are here for. Yes you only want to call setSpriteAnimation to change the current animation. The set animation will be repeated until a new one is set. If you want more control over the animation you can use setSpriteAnimFrame but you will have to control the speed yourself:

                              https://fuzearena.com/help/view/setSpriteAnimFrame

                              1 Reply Last reply Reply Quote 2
                              • lawyerlounge
                                lawyerlounge last edited by

                                Nice! so my example should display the animation on loop? (not at home yet to test it)

                                pianofire 1 Reply Last reply Reply Quote 0
                                • pianofire
                                  pianofire Fuze Team @lawyerlounge last edited by

                                  @lawyerlounge Well I haven't tried it but yes it looks like it should

                                  1 Reply Last reply Reply Quote 0
                                  • waldron
                                    waldron F @Jonboy last edited by

                                    @Jonboy haha i must be to nice

                                    1 Reply Last reply Reply Quote 1
                                    • Jonboy
                                      Jonboy Fuze Team last edited by

                                      ha, but not TOO nice. See, i did it again. Seriously, you should not invite me to comment :-)

                                      1 Reply Last reply Reply Quote 1
                                      • Dave
                                        Dave Fuze Team last edited by

                                        @lawyerlounge My bad! Completely forgot about perhaps the most important command, drawSprites(), in the example I gave.

                                        1 Reply Last reply Reply Quote 0
                                        • First post
                                          Last post