Menu

Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Show posts Menu

Topics - Wampus

#61
Just a thought I had. It is good to protect a game from being interfered with by custom made trainers, DIY trainer tools like CheatEngine or packet editors. Encoding or even encrypting critical variables when you send them across a network or store them in memory or file would be a way to do that. Doing something to prevent cheating is important if you have a game that could be ruined by it, e.g. online multiplayer games and/or a game that relies on slow accumulation of in-game items and stats.

Here is a little bit of code showing a simple example of it could be done:-

Code (glbasic) Select
GLOBAL money%, moneynorm%, ivalue%, uvalue%

WHILE KEY(01) = 0

ivalue = RND(32000) // This is the value to assign to money
uvalue = RND(32000) // This is the value to assign to moneynorm

money = ASL(bXOR(ivalue, 21845), 16)

moneynorm = uvalue

ivalue = 0
uvalue = 0

WHILE KEY (57) = 0

PRINT "Money variable decoded is "+bXOR(ASR(money, 16), 21845), 0, 00
PRINT "Encoded stored value is "+money, 0, 10

PRINT "Moneynorm variable unencoded is "+moneynorm, 0, 30
PRINT "Unencoded stored value is "+moneynorm, 0, 40

PRINT "Press space for next value assignment", 0, 60

SHOWSCREEN

WEND

WEND

END


In the above example the variable money is protected by simple bXOR encoding and a 16bit shift. The variable moneynorm is stored normally. I tested the routine using CheatEngine to "cheat" by trying to find and change the stored variables in memory. It is easy with moneynorm but very difficult with money (without knowing how the value is being encoded). Such a technique won't stop a very determined & experienced cheater but is fairly good basic protection. Its also not very expensive for CPU - its a fast way to do it. It would be possible to encrypt stored variables instead but that would be more CPU intensive and some countries have restrictions on the use of encryption.

Does anyone else use techniques like this or have other ideas about how to protect games from cheaters?
#62
There have been many great horror 3D games but could a 2D game ever be considered scary?

What ways could a 2D game be made to be spooky, unnerving or tense?
#63
How much faster is INLINE for routines that won't need specialised GLBasic commands? Anyone written any code that could be used to compare?

Example of what I would try to use INLINE for: I have an A* pathfinding routine written in GLBasic. The GLBasic PATHFIND() is x2.8 times faster. Previously the speed my routine runs at wasn't an issue for what I was using it for but now I have a use for it that would benefit from as much optimisation as possible.
#64
When I use FINDPATH with heuristic 1.0 the result should be the path with least cost. I'm not sure what heuristic 1.0 is doing but finding the least cost path is definitely not it!

I've attached a little test proggy to demonstrate what I mean. The red path is heuristic 0.0 and the blue path is heuristic 1.0. Lower down the screen is shown the number of path steps that have to be taken and the cost of the path. As you will see, something odd is happening.

Please excuse the awfulness of the code. I wrote the routine a long time ago and just never thought to mention the issue.



[attachment deleted by admin]
#65
I've decided I simply can't put off learning a variation of the C language. I'm thinking I should learn C++ simply because its so widely used for computer game programming. My hesitation is that I already have many books on C# and Objective C that someone bought for me in order to try to encourage me to start learning them instead of C++.

The reason I want to learn is that for some simple but repetitive routines I would need to use in my GLBasic games it would be much faster to use things like IMPORT and INLINE to include C++ code. I'm not new to object-orientated programming because I used to program in Java some years ago so I'm guessing I shouldn't find it too hard to pick up.

C++ would be best, no? And if so, what would be a good start? What kind of development environment do you like to use? i.e. editor, compilers, interpreters? etc.
#66
UPDATE!

The function ShiftColorValue has been improved. The calculations have been optimised and it only does the minimum  work needed to get its result. You can now also saturate and brighten the original sprite more than the original values. All round a better approach. The new routine has been attached to this post.

See my second post below on this thread for an explanation of the ShiftColorValue function

Back to OP:-

---------------------------

Wrote a routine to see how I could use SPRITE2MEM and MEM2SPRITE to create new sprites with different colour schemes. This sort of thing was seen a lot in the 16-bit era. Example screenshot:-



In this demo you can adjust the hue (rainbow bar), the brightness (dark to light bar) and saturation (gray to red bar) of Sagat's flesh, bandages, belt and shorts. Click 'Change' to have a look at the new sprite you've created with your settings and 'Default' to return to default  ;/

Just compile HueShiftExample.gbap to have a look.

[attachment deleted by admin]
#67
I don't know if this is a bug or not. When I run the code included in this post I get two very different times for drawing 30000 identical sets of polygons. They differ in bizarre ways. If you are getting a similar result as me when you run the included code the results should be something like this:

Test 1
10000 of the left polygons in milliseconds: 2925
10000 of the right polygons in milliseconds: 9

Test 2
10000 of the left polygons in milliseconds: 5
10000 of the right polygons in milliseconds: 9304

and then a repeat of the tests shows that each 30000 round of polygons only takes 1 to 10 milliseconds?!?

What is happening here? This must be my graphics card optimising the drawing of these polygons?

Code (glbasic) Select
LOADSPRITE "test.png", 2

GLOBAL time1, time2, time3, time4

// Test 1 for GETTIMERALL() bug

WHILE KEY(01) = FALSE

time1=GETTIMERALL()
STARTPOLY 2,1
FOR p = 1 TO 30000

POLYVECTOR 64, 64, 0, 0, RGB(255, 255, 255)
POLYVECTOR 64, 128, 0, 64, RGB(255, 255, 255)
POLYVECTOR 128, 128, 64, 64, RGB(255, 255, 255)
POLYVECTOR 128, 128, 64, 64, RGB(255, 255, 255)
POLYVECTOR 128, 64, 64, 0, RGB(255, 255, 255)
POLYVECTOR 64, 64, 0, 0, RGB(255, 255, 255)

NEXT
ENDPOLY
time2=GETTIMERALL()

time3=GETTIMERALL()
STARTPOLY 2,1
FOR p = 1 TO 30000

POLYVECTOR 192, 64, 0, 0, RGB(255, 255, 255)
POLYVECTOR 192, 128, 0, 64, RGB(255, 255, 255)
POLYVECTOR 256, 128, 64, 64, RGB(255, 255, 255)
POLYVECTOR 256, 128, 64, 64, RGB(255, 255, 255)
POLYVECTOR 256, 64, 64, 0, RGB(255, 255, 255)
POLYVECTOR 192, 64, 0, 0, RGB(255, 255, 255)

NEXT
ENDPOLY
time4=GETTIMERALL()

PRINT "Test 1", 0, 140

PRINT "30000 of the left polygons in milliseconds: "+INTEGER(time2-time1), 0, 160

PRINT "30000 of the right polygons in milliseconds: "+INTEGER(time4-time3), 0, 180

PRINT "Press mouse button to continue", 0, 200

PRINT "time1: "+time1, 0, 0
PRINT "time2: "+time2, 0, 10
PRINT "time3: "+time3, 0, 20
PRINT "time4: "+time4, 0, 30

SHOWSCREEN

MOUSEWAIT



// Test 2 for GETTIMERALL() bug



STARTPOLY 2,1

time1=GETTIMERALL()
FOR p = 1 TO 30000
POLYVECTOR 64, 64, 0, 0, RGB(255, 255, 255)
POLYVECTOR 64, 128, 0, 64, RGB(255, 255, 255)
POLYVECTOR 128, 128, 64, 64, RGB(255, 255, 255)
POLYVECTOR 128, 128, 64, 64, RGB(255, 255, 255)
POLYVECTOR 128, 64, 64, 0, RGB(255, 255, 255)
POLYVECTOR 64, 64, 0, 0, RGB(255, 255, 255)
NEXT
time2=GETTIMERALL()

time3=GETTIMERALL()
FOR p = 1 TO 30000
POLYVECTOR 192, 64, 0, 0, RGB(255, 255, 255)
POLYVECTOR 192, 128, 0, 64, RGB(255, 255, 255)
POLYVECTOR 256, 128, 64, 64, RGB(255, 255, 255)
POLYVECTOR 256, 128, 64, 64, RGB(255, 255, 255)
POLYVECTOR 256, 64, 64, 0, RGB(255, 255, 255)
POLYVECTOR 192, 64, 0, 0, RGB(255, 255, 255)
NEXT
time4=GETTIMERALL()

ENDPOLY

PRINT "Test 2", 0, 140

PRINT "30000 of the left polygons in milliseconds: "+INTEGER(time2-time1), 0, 160

PRINT "30000 of the right polygons in milliseconds: "+INTEGER(time4-time3), 0, 180

PRINT "Press mouse button to continue", 0, 200

PRINT "time1: "+time1, 0, 0
PRINT "time2: "+time2, 0, 10
PRINT "time3: "+time3, 0, 20
PRINT "time4: "+time4, 0, 30

SHOWSCREEN

MOUSEWAIT

WEND
#68
Does anyone know of a faster way to count the active bits in a byte, word or long than the following example method?

Code (glbasic) Select
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Count the 1s in an 8-bit number                                                                                 //
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

FUNCTION Count8Bits: bit

LOCAL number

IF bit >= 128
DEC bit, 128
INC number
ENDIF

IF bit >= 64
DEC bit, 64
INC number
ENDIF

IF bit >= 32
DEC bit, 32
INC number
ENDIF

IF bit >= 16
DEC bit, 16
INC number
ENDIF

IF bit >= 8
DEC bit, 8
INC number
ENDIF

IF bit >= 4
DEC bit, 4
INC number
ENDIF

IF bit >= 2
DEC bit, 2
INC number
ENDIF

IF bit >= 1
DEC bit, 1
INC number
ENDIF

RETURN number

ENDFUNCTION
#69
    MAJOR UPDATE

    Changes:-


    • Varied levels of visibility (0 - hidden to 8 - fully viewable)
    • Basic Fog of War added
    • Smoothed the edges of the view area
    • Perfect symmetry of view angles
    • No more light leaking through 45 degree edges
    • Greatly improved angles of vision - more natural
    • Radius up to 30 squares (max 20 for uploaded demo)

    Still to do: -


    • Allow for multiple light sources to combine as one
    • Add some nice features like 'keep area permanently viewable'
    • Make it even simpler to plug into a game map with just a few function calls
    • Tidy up the precalculation routine so I can give it to others to modify for themselves

    Nearly there! The hardest parts are all done now.



    -------------------------- Old originals post below --------------------------------


    After seeing that awesome random map generator routine :good: I did some work on a line of sight algorithm...

    The algorithm does a lot more than basic line of sight and solves a couple of problems with the typical approach to line of sight.
    If anyone can think of some useful features to add then say so in this thread. If I think its a good idea I'll add it (and I'll explain why if I don't).

    Also, any ideas about line of sight related stuff in general just post 'em.  :)

    Oh, and use the up and down arrow keys to increase or decrease the line of sight radius in the example.[/list]

    [attachment deleted by admin]
    #70
    There have been some threads about how to keep game movement at a fixed speed, regardless of how many frames per second you app is running at. A recap:-

    MrTAToad's Application Timer (updates movement based on timer) -http://www.glbasic.com/forum/index.php?topic=3512.0
    Bigsofty's conversion of a BB routine to update movement at fixed rate - http://www.glbasic.com/forum/index.php?topic=5297.0
    Simple timer thread - http://www.glbasic.com/forum/index.php?topic=5335.0

    The above is great if an app was written with variable frame rates in mind. However, what if an app was written assuming it would be able to run at a full 60 frames per second? If it is used on platforms that are not fast enough to achieve that screen refresh rate then the app will appear to run more slowly. This is particularly bad for game applications where the movement should be the be same regardless of platform. A couple of solutions:-


    • Rewrite the way the game treats movement so that all of it can be calculated according to a timer
    • Use frameskipping to attempt to catch-up the game speed to the screen refresh rate

    Choice 1 would be ideal. The problem is its very time consuming. If the game is large it would be a very difficult thing to convert all the movement to a timer based approach.

    Choice 2 is less time consuming. Assuming that your game treats game mechanics (movement, play input, changes of status, etc.) and drawing the screen in separate routines, it might be possible to only call the screen drawing routines when there is sufficient time to do so. This will not create the smooth movement of choice 1 but it could mean the difference between a game that is simply broken or at least playable on slower platforms. Its a technique that is often used in emulators with acceptable results

    I'm going to see if I can achieve the 2nd approach using GLBasic today. If anyone has done this before or has any ideas about how to do it in GLBasic please post a response in this thread. I'll post my code and the results at the end of the day, even if I fail.
    #71
    Just a vent thread really. Join in if you've felt the pain I am about to describe!

    So, after a break/illness that lasted too long I am very close to releasing an initial game for iDevice. It looks lovely on a 3GS with 60FPS and interesting visual FX. 1st & 2nd generation iPhone/iPod Touch? Annoying! They can only manage a steady 30FPS with the best visual FX removed. Its still very playable but I'm disappointed. The same goes for my other two projects - if I want anything fancy I have to take an FPS hit to 30FPS (at least) on 1st & 2nd generation.
    #72
    I'm wondering about going into app development full-time as an indie developer.

    My logic is that, even if I'm a commercial failure, I will have learnt enough in the process to move on to employment or contract work. Currently I'm pretty much a computer technician by training & experience. However, I feel much more suited to software engineering in general and I think the quickest & best way to jump ship quickly would to be go it alone for a while. My knowledge & skills definitely need to be improved and that's not going to happen in a hurry unless I devote some serious time to this stuff.

    I'm sure some of you wonder about this sort of thing or already work full-time as developers. Do you think my idea has potential? What have been your experiences?

    #73
    I've attached a small proggy with sourcecode. All it does is use Polyvector to draw tiles side by side, then scales them in and out.

    At 1:1 ratio tiles are seemless. However, when not at 1:1 there are often clear divisions between the tiles. How can this be prevented?



    [attachment deleted by admin]
    #74
    Sometimes a sprite is much more than is needed!

    The sprite related functions of GLBasic are great for most 2D things; wonderful and very powerful. However, sometimes it would be very useful when speed is a necessity to be able to treat simple image copying as purely image copying, a bit like the BLIT command request from this thread: http://www.glbasic.com/forum/index.php?topic=3084.0

    The reason I ask is because of this thread: http://www.glbasic.com/forum/index.php?topic=5007.0

    In order to create the 2D water ripple effect I used an old 16-bit era technique to draw the background image line by line. On an iPhone screen that's 480 calls of DRAWANIM to fill the screen. Unfortunately DRAWANIM is CPU expensive so I can't use this technique without taking a big FPS hit, making it no good for 60 FPS games.

    This is the forth time I've found a reason to draw a big image line by line in order to create certain effects. If there was a crude, cheap but fast way of copying an image I would benefit a lot from that.

    Alternatively I could just learn enough C/C++ to do it using INLINE or something like that.

    Do you think there is a need for a simpler but faster image copying command?
    #75
    So, I did a quick routine to create a classic 2D water ripple effect. The code, exe and test image are all included in the attachment.



    On my 32GB iPod Touch (3rd generation - quite powerful) it really struggles, reducing framerate to a crawl and is thus not usable for anything that requires 60 FPS.

    Is anyone aware of a way to do this kind of ripple effect without having to load and then draw a sprite as a line-by-line animation? Although covering the screen line by line could be very fast, if that was all that was involved, having to use the DRAWSPRITE command to do it is considerably CPU expensive. This kind of ripple effect was possible without too much trouble even on 16-bit computers but calling DRAWSPRITE 480 times to fill the screen even slows the FPS on my netbook.

    I don't need any alpha-blending, collision detection or anything like that so is there any way to do what I've done without DRAWSPRITE?

    Code (glbasic) Select
    LOADANIM "test.png", 1, 340, 1

    GLOBAL waters[]
    DIM waters[480]
    GLOBAL f = 0

    FOR n = 0 TO 3

    FOR i = 0 TO 119

    waters[i+(n*120)] = 5*SIN(f)

    INC f
    INC f
    INC f

    IF f >= 360 THEN f = f-360

    NEXT

    NEXT


    f = 0


    // MAIN LOOP
    WHILE KEY(01) = FALSE
    //MAIN LOOP


    FOR i = 0 TO 479           

        DRAWANIM 1, i+5-waters[f], waters[f]-5, i            // Draw every single line as a sprite

    INC f

    IF f = 480

        f = f - 480

    ENDIF

    NEXT

    DEC f

    SHOWSCREEN

    WEND

    END


    [attachment deleted by admin]
    #76
    Beta Tests / PowFish
    2010-Aug-29
    PowFish will be my first complete game in GLBasic. Hopefully there will be many more. Currently there is a lot of work to do on this game but I hope to get a big update finished by Thursday. I aim to put it on the AppStore but make it free to download for PC and Mac.  :)

    Gameplay:

    • Get 4 or more sea creatures connected by adjacent positions to get a score
    • Do not let the timer reach nothing! The timer will increasingly speed up as you play
    • If you get stuck or see an opportunity for a big combination you can use a swap. Double-tap a sea creature to swap it to its opposite colour
    • The more sea creatures in any combo the more bonus points you will get. You may even get bonus swaps if you make a very large combination
    • Bonus powers occasionally become available when you see a shell. Explode any combo near the shell to reveal your bonus power. Double-tap to use

    Currently only Arcade mode is working.

    Let me know what you think. What's good? What's bad? Improvements?

    Thanks  =D

    btw I only uploaded a Windows version because of file size restrictions

    [attachment deleted by admin]
    #77
    As well as rotation it would be useful to have horizontal & vertical flipping for sprites. Currently I have to draw sprites line by line as an animation to flip them.

    Some possibilities: Easy way to create reflection effects for surfaces, simply flipping horizontal to make a sprite change its direction from left to right, symmetry effects.
    #78
    In two to three days I will be into Beta testing my first game in GLBasic (so will need to purchase a full license!) It easily runs at optimum speed on my PC test platforms but I suspect portable devices might struggle because of the amount of layered 2D images on screen. Having options to turn down detail seems a good idea but that also got me thinking that my code was really messy and I should optimise it.

    Do you have any tips for optimising code? What kind of commands or approaches do you know to be processor expensive compared to alternatives? Let's discuss.

    I also have a specific question: Are GLOBAL variables inherently faster than creating LOCAL variables in Function calls? My game currently uses a lot of LOCALs and I'm thinking creating and releasing these variables may take up extra time.
    #79
    http://www.youtube.com/watch?v=pWYgM1RGixM

    Check out the DS 3D above. Soon netbooks/lappies, consoles and workstations are going to get 3D screens like this. 3D TVs are already been sold. This is going to be BIG!

    When all this takes off and Mac/PC support becomes available, please please please get GLBasic to work with real 3D depth as soon as possible!

    I'm already thinking about what I could do with a 3D screen.  So many possibilities. Even traditionally 2D graphics could be hugely improved by layers of depth. :S Gah, can't stop dreaming. Want it, now, for my netbook!  :blink:

    What would you do with a 3D screen? Would it change the kind of games you'd want to create?
    #80
    Fighting games often have complicated series of steps to perform special moves, e.g. down, down & forward, forward & fire to perform Ken's Shoryuken fireball attack.

    I wrote some code to see what it would require to add such moves into a control scheme. After that I realised I'd never use it anyway (I like writing strategy games, not action games).

    The code below was written to accomodate:-

    • charging up fire (or jump)
    • step by step special moves
    • rapid fire moves

    I was going to add hold & release moves, e.g. hold down for 2 seconds then press up & fire, but that was when I got tired of writing code I wasn't going to use.  ::)

    Built into the routine are dash special moves (tap left or right quickly), a Dragonpunch in either direction (like Street Fighter 2) and rapid fire (like Chun Lee's Hundred Rending Kicks)

    The code supports up to 10 joypads. This is in theory because I have the trial of GLBasic so can't test this more than making sure the syntax is correct. The code is a bit of an obscure mess and would best be tailored for particular needs. However, if anyone did want this done I would re-write the code for their needs.

    First part below

    Code (glbasic) Select

    SETSCREEN 640,480,0
    LIMITFPS 60
    LOADFONT "smallfont.png", 1 // A workaround because the default font won't load by, er, default

    TYPE allpad
    sfjoypad% // The joypad number that will be used. Can be 1 to 10. (Who has 10 joypads?!)
    sfdirection% // The direction the joypad is in. 9 = no direction : 1 = up right : 2 = right : 3 = down right : 4 = down : 5 = down left : 6 = left : 7 = up left : 8 = up
    sffire% // How long the FIRE button has been pressed. 1 = new bullet/punch/whatever. Numbers bigger than 1 used for build up to a super shot in R-Type or MegaMan where the fire button is held down to charge and released to fire.
    sfjump% // How long the JUMP button has been pressed. Might be useful for super-jumps or whatnot.
    sfspecial% // Number of special moves joypad n should be configured for
    sfmaxmove% // Maximum steps in any one special move. Used for limiting dimensional array usage
    sfmoves%[] // Array for holding the steps of special moves in.
    sftypemove%[] // The type of special move. 1 = step by step. 2 = rapid fire. 3 = build up. The build up type hasn't been completed in this example
    sftolerance%[] // Higher = easier to execute special moves. How long should slips of joypad be ignored before next step HAS to be completed?
    sfmovewait%[] // higher = easier to execute special moves. How long can you be holding a direction before the step in a special move is considered void
    sfmovestate%[] // which step is the special move currently in? 0 = not in any state
    sfmovecounter%[] // Variable to check how long the move state has been in one state
    sfmovetolerance%[] // Variable to check gow long the move been out of sequence
    sfendmove%[] // Which is the final move in the combination? When reached, set sfmovestate to 255
    sfcanignorefire%[] // Can you charge your gun while performing this move? If yes, then ignore fire & jump status while checking.
    firebutton% // Set button used to shoot on Joypad - used for non-trial GLBasic only
    jumpbutton% // Set button used to jump on Joypad - used for non-trial GLBasic only
    keyright% // Set key for right
    keydown% // Set key for down
    keyleft% // Set key for left
    keyup% // Set key for up
    keyfire% // Set key for fire
    keyjump% // Set key for jump
    ENDTYPE

    GLOBAL sfPad[] AS allpad // Possibility of up to 10 joysticks but only one used in this code

    // Initialise the JoyPad settings. Any number of settings can be set for one joypad, though here I am just setting up one configuration
    // Muliple settings is useful for games where the controls can change often. e.g. Street Fighter games, where the direction you are facing
    // changes the kind of special moves that are available to you. It could also be useful for Megaman types games where weapons layouts change

    LOCAL pla1

    pla1 = sfPadInitialise(1,7,4) // pla1 will be configured for joypad 1, will have 6 special moves and 4 steps is the maximum number for any special move

    // Define Controls for pla1, i.e. player 1

    sfPadDefaultControls(pla1)

    // Add pre-defined special moves into the 6 slots set out by sfPadInitialise(*,6,*)
    // Obviously, don't try to add any moves or check for them if you haven't specified that the joypad configuration will need some

    sfPadAddMove("right dash", pla1, 0) // tap right twice quickly
    sfPadAddMove("left dash", pla1, 1) // tap left twice quickly
    sfPadAddMove("right dragonpunch", pla1, 2) // right, down, down + right, right + fire
    sfPadAddMove("right dragonpunch slip", pla1, 3) // included to make dragonpunch easier for noobs (e.g. my complaining gf)
    sfPadAddMove("left dragonpunch", pla1, 4) // left, down, down + left, left + fire
    sfPadAddMove("left dragonpunch slip", pla1, 5) // included to make dragonpunch easier for noobs
    sfPadAddMove("fast fire", pla1, 6) // press fire repeatedly as quick as possible to active fast fire move

    // Main test loop

    spectimer% = 0
    s$=""

    WHILE TRUE

    sfPadState(pla1) // Check what the state of the joypad and special moves are in

    dire=sfPad[pla1].sfdirection

    SELECT dire

    CASE 9
    PRINT "direction: no movement", 0, 0
    CASE 1
    PRINT "direction: up & right", 0, 0
    CASE 2
    PRINT "direction: right", 0, 0
    CASE 3
    PRINT "direction: down & right", 0, 0
    CASE 4
    PRINT "direction: down", 0, 0
    CASE 5
    PRINT "direction: down & left", 0, 0
    CASE 6
    PRINT "direction: left", 0, 0
    CASE 7
    PRINT "direction: up & left", 0, 0
    CASE 8
    PRINT "direction: up", 0, 0
    DEFAULT
    PRINT "direction: Whoops! An error.", 0, 0
    ENDSELECT

    PRINT "Imma chargin' mah lazer: " + sfPad[0].sffire, 0, 16
    PRINT "Jump pressed for: " + sfPad[0].sfjump, 0, 32

    IF spectimer > 0
    DEC spectimer
    PRINT "Special Move:" + s$, 0, 80
    ENDIF

    IF sfPad[pla1].sfmovestate[0]=255
    spectimer = 120
    s$="A dash to the right!"
    ENDIF

    IF sfPad[pla1].sfmovestate[1]=255
    spectimer = 120
    s$="A dash to the left!"
    ENDIF

    IF sfPad[pla1].sfmovestate[2]=255 OR sfPad[pla1].sfmovestate[3]=255
    spectimer = 120
    s$="Dragonpunch to the right!"
    ENDIF

    IF sfPad[pla1].sfmovestate[4]=255 OR sfPad[pla1].sfmovestate[5]=255
    spectimer = 120
    s$="Dragonpunch to the left!"
    ENDIF

    IF sfPad[pla1].sfendmove[6]=255
    spectimer = 4
    s$="Very fast hitting!"
    ENDIF

    SHOWSCREEN

    WEND
    END