Programming C, C++, Java, PHP, Ruby, Turing, VB
Computer Science Canada 
Programming C, C++, Java, PHP, Ruby, Turing, VB  

Username:   Password: 
 RegisterRegister   
 2D Platformer Detection and scrolling
Index -> Programming, Turing -> Turing Help
View previous topic Printable versionDownload TopicSubscribe to this topicPrivate MessagesRefresh page View next topic
Author Message
haayyeess




PostPosted: Sat Jan 16, 2016 4:35 pm   Post subject: 2D Platformer Detection and scrolling

What is it you are trying to achieve?
I'm creating a 2D platformer as a part of a project. Because of some poor design during the design process, it's become very challenging. The use of processes (not my idea) doesn't help.


What is the problem you are having?
- Currently the user can fall below ground and get stuck sometimes.
- They can also get stuck in air sometimes (ground level is set too high, even when it shouldn't be set) I believe this is because things are running at different speeds....
- I am not sure how to handle paging, or scrolling... Text file uses string values, which I can't make go into the negative for scrolling...

I'm willing to host someone through a Teamviewer meeting in order to look at the problems. It's hard to show and explain in a post.

Post any relevant code (You may choose to attach the file instead of posting the code if it is too long)
<Answer Here>
GRID DETECTION
Turing:


%Grid_Load loads in the grid map to correspond with the running
    %display, it will advance screens as required.  Called by detection
    %sends back grid coors to detection
    %GRID LOAD
procedure Grid_Load (var GridMap : array 0 .. 36, 0 .. 36 of string (1))

    %LOCAL VARIABLES
    var FileNo : int  %int cuz turing for loading in file
    var FileName : string  %name of file

    %DECIDE WHICH FILE TO OPEN
    case (CharLevel) of
        label 11 :
            FileName := "Maps\\Level-1 Map.txt"
        label 12 :
            FileName := "Maps\\Level-12 Map.txt"
            %FileName := "Maps\\Level-2 Map.txt"
        label 13 :
            %FileName := "Maps\\Level-3 Map.txt"
        label 21 :
            %FileName := "Maps\\Level-3 Map.txt"
        label 22 :
            %FileName := "Maps\\Level-3 Map.txt"
        label 23 :
            %FileName := "Maps\\Level-3 Map.txt"
        label 31 :
            %FileName := "Maps\\Level-3 Map.txt"
        label 32 :
            %FileName := "Maps\\Level-3 Map.txt"
        label 33 :
            %FileName := "Maps\\Level-3 Map.txt"
        label 41 :
            %FileName := "Maps\\Level-3 Map.txt"
        label :
            %Just cuz turing
    end case

    %LOAD MAP
    open : FileNo, FileName, get
    for decreasing y : 36 .. 0     % for every y
        for x : 0 .. 36     %for every x
            get : FileNo, GridMap (x, y)     %get the tile type at (x,y)
        end for
    end for
    close (FileNo)

end Grid_Load

%Grid_Detection is a process used to detect possible collisions between the
% User's character and objects.  Ideally Grid_Detection will check the player's
% future movement each space at a time to determine if the movement is doable.
%Grid_Detection relies on an external file known as a Level Render to know
% the (X,Y) coordinates of blocks, spikes and saves.
%GRID DETECTION
process Grid_Detection

    %LOCAL VARIABLES
    var GridMap : array 0 .. 36, 0 .. 36 of string (1)

    %LOCAL VARIABLE ASSIGNMENTS
   
    %GET A MAP IN HERE
    Grid_Load (GridMap)
    %Always has a level to work with when entering into main loop
    %whether it's a brand new game, or something loaded by user


    loop %MAIN DETECTION LOOP
        %CHECKING FOR END OF SCREEN\LEVEL
        if PlayerXLoc = 680 then %End of level
            if natstr (CharLevel) (*) = "3" then %End of map reached
                CharLevel := CharLevel + 8 %Advance to next level
                Grid_Load (GridMap)%Load new map
            else %End of screen 1 or two, advance screen
                CharLevel := CharLevel + 1
                Grid_Load (GridMap) %Load new map
            end if
        end if

        %DETECTING OBJECTS USING GRID
        %X-DIRECTION
        %MOVING RIGHT * 20 to scale
        if (GridMap (floor((PlayerXLoc + PLAYERXRAD + 20) / 20), ceil ((PlayerYLoc + PlayerYRad) / 20)) = "B") or %Right Top
                (GridMap (floor ((PlayerXLoc + PLAYERXRAD + 20) / 20), floor ((PlayerYLoc - PlayerYRad) / 20)) = "B") then %Right Bottom
            MovementFwdOK := false     %Blocked
        else
            MovementFwdOK := true
        end if

        %MOVING LEFT * 20 to scale
        if GridMap (ceil ((PlayerXLoc - PLAYERXRAD - 20) / 20), floor ((PlayerYLoc + PlayerYRad) / 20)) = "B" or %Left Top 
           GridMap (ceil ((PlayerXLoc - PLAYERXRAD - 20) / 20), ceil ((PlayerYLoc - PlayerYRad) / 20)) = "B" then %Left Bottom
            MovementBackOK := false
        else
            MovementBackOK := true
        end if

        %Y-DIRECTION
        %MOVING UP * 20 to scale
        if GridMap (floor ((PlayerXLoc + PLAYERXRAD) / 20), floor ((PlayerYLoc + 20 + PlayerYRad) / 20)) = "B" or %First up Right
                GridMap (ceil ((PlayerXLoc - PLAYERXRAD) / 20), floor ((PlayerYLoc + 20 + PlayerYRad) / 20)) = "B" or %First up Left
                GridMap (floor ((PlayerXLoc + PLAYERXRAD) / 20), floor ((PlayerYLoc + 40 + PlayerYRad) / 20)) = "B" or %Second up Right
                GridMap (ceil ((PlayerXLoc - PLAYERXRAD) / 20), floor ((PlayerYLoc + 40 + PlayerYRad) / 20)) = "B" then %Second up Left
            MovementUpOK := false
            %20 is the radius, removed from equation to avoid flicker when changing size
        else
            MovementUpOK := true
        end if

        %MOVING DOWN * 20 to scale
        if GridMap (floor((PlayerXLoc + PLAYERXRAD) / 20), ceil ((PlayerYLoc - 20 - PlayerYRad) / 20)) = "B" or %down right
                GridMap (ceil ((PlayerXLoc - PLAYERXRAD) / 20), ceil ((PlayerYLoc - 20 - PlayerYRad) / 20)) = "B" then %down left
            OnGround := true     %Can't go down assume on ground
            GroundLevel := PlayerYLoc - PlayerYRad %Set ground level as the block below char to ensure stays above
        else %Must be in air
            OnGround := false 
        end if

        %POLING LOOP
        if PauseProcess then
            loop
                exit when not PauseProcess
            end loop
        end if

    end loop %END OF MAIN DETECTION LOOP

end Grid_Detection



RENDER SCREEN
Turing:

% Render_Screen put's everything possible to be displayed on the screen on
    % the screen, and removes it as required.  Render_Screen loads and draws
    % images when needed, and relies highly on communications from
    % User_Controls and Grid_Detection in the form of global variables and
    % flags.
process Render_Screen

    %LOCAL VARIABLES
    var BackGround : int %Background for level one
    var BGX : int % background pic x coor, int for turing
    var BGY : int % background picture y coor, int for turing
    %var Character : int
    %Character := Pic.FileNew ("Graphics\\Game Graphics\\Character.jpg")

    %testing below.....
    var TestMap : array 0 .. 36, 0 .. 36 of string (1)  %TEST
    var FileNo : int  %FOR TEST
    var FileName : string  %FOR TEST

    %LOCAL VARIABLE ASSIGNMENTS
    BGX := 0
    BGY := 0

    %below for test
    FileName := "Maps\\Level-1 Map.txt"

    %DECIDE BACKGROUND (off start)
    if natstr (CharLevel) (1) = "1" then
        BackGround := Pic.FileNew ("Graphics\\Game Graphics\\Level-1.jpg")
    elsif natstr (CharLevel) (1) = "2" then
        %Pic.Draw (Lvl2BG,0,0,0)
    elsif natstr (CharLevel) (1) = "3" then
        %Pic.Draw (Lvl3BG,0,0,0)
    else
        %Pic.Draw (Lvl4BG,0,0,0)
        %Draw boss map
    end if

    %SET SCREEN SIZE
    View.Set ("Graphics:740;740,offscreenonly")

    loop %MAIN DRAWING LOOP

        %DRAW BACKGROUND
        Pic.Draw (BackGround, BGX, BGY, 0)
        %Last minute above ground check (here to prevent change)
        if (PlayerYLoc - PlayerYRad) < GroundLevel then
            PlayerYLoc := GroundLevel + PlayerYRad
        end if
        %DRAW CHARACTER
        Draw.FillOval (PlayerXLoc, PlayerYLoc, PLAYERXRAD, PlayerYRad, CharColor)
        %Pic.Draw (Character, (PlayerXLoc), (PlayerYLoc), picMerge)
        %x, y, xRadius, yRadius, Color : int


        % %TEST
        locate (1, 1)
        put "X coor Game", PlayerXLoc
        put "Y coor Game ", PlayerYLoc
        put ""
        put "Playr x vel ", PlayerXVel
        put "Player y vel ", PlayerYVel
        put ""
        put "X coor Grid ", PlayerXLoc / 20
        put "Y coor Grid ", PlayerYLoc / 20
        put ""
        put "up ok ", MovementUpOK
        put "on ground ", OnGround
        put "ground level ", GroundLevel
        put "Y RAD ", PlayerYRad  %WORKING 100%
        %

        View.Update %update

        %IF USER IS AT END OF SCREEN
        if PlayerXLoc = 680 then
            %DECIDE BACKGROUND
            if natstr (CharLevel) (*) = "3" then %END OF LEVEL REACHED
                if natstr (CharLevel) (1) = "1" then
                    BackGround := Pic.FileNew ("Graphics\\Game Graphics\\Level-1.jpg")
                    Pic.Draw (BackGround, 0, 0, 0)
                elsif natstr (CharLevel) (1) = "2" then
                    %Pic.Draw (Lvl2BG,0,0,0)
                elsif natstr (CharLevel) (1) = "3" then
                    %Pic.Draw (Lvl3BG,0,0,0)
                else
                    %Pic.Draw (Lvl4BG,0,0,0)
                    %Draw boss map
                end if
                BGX := 0  %Reassign to start of picture cuz new level
            else %USER IS NOT AT END OF LEVEL, ADVANCE SCREEN
                BGX := BGX + 740 %SHIFT BG PICTURE TO LEFT (NEW SCREEN)
            end if
        end if

    end loop     %END MAIN DRAWING LOOP
end Render_Screen


USER CONTROLS
Turing:

%PLEASE SEE THE MAIN MENU FOR MORE INFORMATION INCLUDING GLOBAL VALUES

%#%#%#%%#%#%#%#%%#%#%#%#%%#%#%  USER CONTROLS  #%#%%#%#%#%#%#%#%#%#%%#%#%#%#%#
/*User Controls is the subprogram responsible for all of the in-game action
 requiring user input.  User_Controls is constantly checking for user input and
 storing entered keys in order to see if they control a function.  Any key
 without a function is ignored.  Based on the entered keys, User_Controls
 follows through with an action of character movement, or entering the
 Pause_Menu.  User_Controls updates global variables as required to notify
 processes in gameplay of required action.

 *%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%
 %*%                USER CONTROLS CONSTANT AND VARIABLE LIST                %*%
 %*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*%*
 $$$$$$$$$$$$$$$$$$$$$$$$$ CONSTANTS $$$$$$$$$$$$$$$$$$$$$$$$$
 %LOCAL
 JUMPSPEED: Value regulating the speed and height a user can jump in Y
 direction per key.
 RUNSPEED: Value regulating the speed and distance a user moves in the X
 direction per key.
 
 %GLOBAL
 GRAVITY: Value regulating how fast a player's Y velocity and height is
 returned to 0 after jump.
 PLAYERXRAD: Stores the player's radius value for the X direction.

 $$$$$$$$$$$$$$$$$$$$$$$$$ VARIABLES $$$$$$$$$$$$$$$$$$$$$$$$$
 %LOCAL
     Chars: ARRAY CHAR OF BOOLEAN, stores pressed keys and used for
 keyboard movement.
 
 %GLOBAL
 StopProcess: Boolean flag set when a user exits from within in-game play,
 initially false.
 PauseProcess: Boolean flag set when a user enters the pause menu,
 initially false.
 MovementUpOK: Boolean flag set when a user's next possible upward position
 will not interfere with object.
 MovementFwdOK: Boolean flag set when a user's next possible forward position
 will not interfere with object.
 MovementBackOK: Boolean flag set when a user's next possible backward position
 will not interfere with object.
 OnGround: Boolean flag set when the user is on the ground level,
 set initially true.
 PlayerXLoc: NAT 2 variable storing the user's X location upon saving
 their last game.
 PlayerYLoc: NAT 2 variable storing the user's Y location upon saving
 their last game.
 PlayerXVel: REAL 4 variable storing the user's X direction velocity,
 or speed.
 PlayerYVel: REAL 4 variable storing the user's Y direction velocity,
 or speed.
 PlayerYRad: NAT 1 variable storing the player's radius value for
 the Y direction.
 GroundLevel: NAT 2 variable storing the ground level.

 */

 
 %SUBPROGRAMS
 %PAUSE_MENU
 include "Pause_Menu.t"

procedure User_Controls

    %LOCAL CONSTANTS
    const RUNSPEED := 20 %Numeric, controls speed (step) of users run (X-Dir)
    const JUMPSPEED := 40 %Numeric, controls speed (step) of users jump (Y-Dir)
   
    %LOCAL VARIABLES
    var Chars : array char of boolean %Allows user to make choices throughout prog
    var ShiftChar, ShiftChar2 : boolean %For shifting character ONCE after or when down is prsd
    var NoAccumGravity : boolean %Flag for preventing the accumulation of
        %gravity to prevent the bullet through paper effect of too fast movmnt
       
    %LOCAL VARIABLE ASSIGNMENTS
    OnGround := true %dropping user from air
    ShiftChar := false %not yet
    ShiftChar2 := false
    NoAccumGravity := true
   
    loop
        Input.KeyDown (Chars) %Allow user input, track for action

        %PAUSE CHECK
        if Chars (' ') then %Spacebar was pressed
            PauseProcess := true %Turn pause flag ON
            Pause_Menu %Call Pause
        end if

        %X DIRECTION, (LEFT-RIGHT) MOVEMENT CHECK
        if Chars (KEY_RIGHT_ARROW) and MovementFwdOK then
            PlayerXVel := RUNSPEED % Assign X velocity pos. runspeed
        elsif Chars (KEY_LEFT_ARROW) and MovementBackOK then
            PlayerXVel := -RUNSPEED % Assign X velocity neg. runspeed
        else
            PlayerXVel := 0 % Assign X velocity 0, stop x-dir movement
            %will change if add sloped rolling, possible v2.
        end if
       
        %GRAVITY EFFECT
        if not OnGround then
            PlayerYVel := (PlayerYVel - GRAVITY)
            %prevent from getting too fast
            % if PlayerYVel < -40 then
            %     PlayerYVel := -40
            % end if
        else
            PlayerYVel:= 0
        end if

        %Y DIRECTION, (UP-DOWN) MOVEMENT CHECK
        if Chars (KEY_UP_ARROW) and MovementUpOK and OnGround then
            PlayerYVel := JUMPSPEED
        elsif Chars (KEY_DOWN_ARROW) and OnGround then
            PlayerYRad :=  round (0.5 * PLAYERXRAD) %will always be whole
            ShiftChar := true
            if ShiftChar2 then
                PlayerYLoc := PlayerYLoc + round (PLAYERXRAD)
                ShiftChar2 := false
            end if
            %
        elsif not Chars (KEY_DOWN_ARROW) and MovementUpOK and ShiftChar then
                PlayerYRad := PLAYERXRAD
                PlayerYLoc := PlayerYLoc + round (0.5 * PLAYERXRAD)
                ShiftChar := false
                ShiftChar2 := true
        end if
       
        %DO MOVEMENT
            PlayerXLoc := PlayerXLoc + ceil (PlayerXVel)
            PlayerYLoc := PlayerYLoc + ceil (PlayerYVel)

        %CHECK FOR EXIT
        exit when StopProcess
       
        delay (50) %to slow things down a wee bit and regulate speed
    end loop
end User_Controls
Sponsor
Sponsor
Sponsor
sponsor
Insectoid




PostPosted: Sat Jan 16, 2016 5:12 pm   Post subject: RE:2D Platformer Detection and scrolling

You're going to want to completely remove processes from your program. They are going to (and likely already have) cause you a ton of headaches, especially where multiple processes access the same variables (which your program does).

Remember, processes do not (generally) run simultaneously. They take turns. Process A runs for a few milliseconds, then process B takes over. Process A can't trust variables from process B and vice versa, because neither process has any idea how far the other is in its execution.

For example, your variable 'movementfwdok' is used by both grid_detection and user_controls. user_controls checks this variable to determine if the player can move. What if user_controls completes two frames before grid_detection finishes calculating movefwdok? Movefwdok will be out of date, and your character might be able to move through a wall, or be blocked where there is no wall.

This will cause extreme issues where a process pauses halfway to let another take over and a lot of variables are shared. a process may be halfway done calculating a new frame, and then pause. The next process that uses those variables will have only half the data from the current frame, while the other half is from the previous frame, so the process will give completely incorrect results.

Long processes may pause several times before completing, so processes depending on them will have a mix of data from several frames, which will seriously fragment your program and even crash it. I'm sure by now you realize how massive your problem is.


I'm afraid there is no way to salvage your current work. It's not a quick fix. You'll need to completely reorganize it to eliminate processes from your code. Most of actual lines can be saved, but will have to be totally rearranged. Make sure you are familiar with the fundamentals of a game loop before carry this out.
haayyeess




PostPosted: Sat Jan 16, 2016 5:42 pm   Post subject: Re: 2D Platformer Detection and scrolling

Thank you Insectoid. Could you please example what you mean about the "fundamentals of a game loop"?
Insectoid




PostPosted: Sat Jan 16, 2016 5:55 pm   Post subject: RE:2D Platformer Detection and scrolling

Every successful game in Turing looks more or less the same. Everything takes place sequentially inside one big loop. You shouldn't have any other loops in there unless you know what you're doing. The basic structure is as follows:
code:
loop
Input.KeyDown
    %Update everything by one frame.
    %Draw everything
    View.Update
    delay
    cls
end loop


The important bit here is 'update everything by one frame'. One frame. I'm repeating myself, but there should be no loops in here unless you know what you're doing. Here is where you deal with user input, check for collisions and respond to them, update the AI and the player's scores, whatever. Anything that changes, changes here, and it only changes by one frame.

If you stick to this template, your game will run smoothly and your code will be easy to read. Bugs will be generally obvious and everything is predicable.
haayyeess




PostPosted: Sat Jan 16, 2016 6:18 pm   Post subject: Re: RE:2D Platformer Detection and scrolling

Insectoid @ Sat Jan 16, 2016 5:55 pm wrote:
Every successful game in Turing looks more or less the same. Everything takes place sequentially inside one big loop. You shouldn't have any other loops in there unless you know what you're doing. The basic structure is as follows:
code:
loop
Input.KeyDown
    %Update everything by one frame.
    %Draw everything
    View.Update
    delay
    cls
end loop


The important bit here is 'update everything by one frame'. One frame. I'm repeating myself, but there should be no loops in here unless you know what you're doing. Here is where you deal with user input, check for collisions and respond to them, update the AI and the player's scores, whatever. Anything that changes, changes here, and it only changes by one frame.

If you stick to this template, your game will run smoothly and your code will be easy to read. Bugs will be generally obvious and everything is predicable.


Thank you so much. Huge code roll over here I come.
Display posts from previous:   
   Index -> Programming, Turing -> Turing Help
View previous topic Tell A FriendPrintable versionDownload TopicSubscribe to this topicPrivate MessagesRefresh page View next topic

Page 1 of 1  [ 5 Posts ]
Jump to:   


Style:  
Search: