Medieval Dreams

Started by William, July 12, 2023, 20:29:04

Previous topic - Next topic

William

Medieval fantasy multiplayer game servers & matches, feudalism fiefdom, kingdoms & maybe magic.

presently, i am attempting to write multiplayer, specifically multiplayer player movement.

My project https://github.com/zarosath/MedievalDreams.io

So far singleplayer movement/mouse controls are working and basic net has been implemented and animations need done that is next.
im still interested in oldschool app/gamedev

William

#1
my head isnt in it. i havent coded for months, it may take some time getting back into the code understanding edit: what i can do, presently i am at a day center for mental health. i have much confusion. The code needs to be classified and i have to learn object orientated programming on the way.
im still interested in oldschool app/gamedev

Midimaster

The multi-players should be accessable in a list inside the client. Lets say, you have 3 players: one is the man that sits in front of the computer and two are the guys from outside. Here is a possible start-up:

Global CONST G_NAME:Int=1

Type TPlayer
    Global All:TList = New TList
    Field X:Int, Y:Int, Name:String
    Field GObj:TGNetObject


    Function CreateMe:TPlayer(Name:String)
         local loc:TPlayer = New TPlayer
         loc.Name = Name
         List.AddLast loc
         Return loc
    End Function


    Function AddOther(obj:TGNetObject)
         local loc:TPlayer = New TPlayer
         GObj= obj
         loc.Name = GetGNetString( obj, G_NAME)
         List.AddLast loc
    End Function


    Function Check()
         Print "List of members:"
         For local loc:TPlayer= Eachin All
              Print loc.Name + " " + loc.X
         Next
    End Function


    Method Connect()
       GObj= CreateGnetObject(Host)
       SetGNetString GObj, G_NAME, Name
    End Method
End Type

Local InputName:String = Input("What is your name")
Global MePlayer:TPlayer = TPlayer.CreateMe(InputName)

MePlayer.Connect

Repeat
   TPlayer.Check
   CheckNewMembers
   Delay 1000
Until AppTerminate()


Function CheckNewMembers()
    Local list:TList = GNetObjects(Host, &GNET_CREATED)
    For local obj:TGNetObjects = EachIn list
       TPlayer.AddOther obj
    Next
End Function


The code is not testet, I wrote it on-the-fly
...back from Egypt

William

Roadbump unable to access a type instance defined or created within a for loop as it is not global or something.

Type TPlayer

Field Username:String
Field x: Float
Field y: Float
Field PlayerIsOnGround:Int
Field YAcceleration:Float
Field playerentity:TEntity = CopyEntity(Player)

End Type

For Local obj:TGNetObject=EachIn GNetObjects( host,GNET_ALL )
global example1:TPlayer = New TPlayer
      If obj=localplayer
   SetGNetFloat LocalPlayer,GNET_PLAYER_X,example1.x
   SetGNetFloat LocalPlayer,GNET_PLAYER_Y,example1.y
SetGNetString( LocalPlayer,31,example1.Username)
         ' that is me
      Else
         'Local Name:String = GetGNetString(obj,31)
         'Print "name =" + Name
      EndIf
Next
Print example1.x

identifier example1 not found.
im still interested in oldschool app/gamedev

Midimaster

#4
following my first example you can forget the FIELDS and use METHODES to directly aks GNET for properties of the players:

In the past you stored the X property in the field X:Int. But it is possible to investigate X directly from the GNet each time you need it.

Instead of writing Player.X we now write Player.X(), because X() is now a method, which calls GNet to tell us X.



Global CONST G_NAME:Int=1
Global Const G_X:Int=2

Type TPlayer

    Global All:TList = New TList
    Field GObj:TGNetObject

    Function CreateMe:TPlayer(Name:String)
         local loc:TPlayer = New TPlayer
         loc.Connect Name
         All.AddLast loc
         Return loc
    End Function

    Function AddOther(obj:TGNetObject)
         local loc:TPlayer = New TPlayer
         loc.GObj = obj
         All.AddLast loc
    End Function

    Function Check()
         Print "List of members:"
         For local loc:TPlayer= Eachin All
              Print loc.Name() + " " + loc.X()
         Next
    End Function

    Method Connect(Name:String)
       GObj= CreateGnetObject(Host)
       SetGNetString GObj, G_NAME, Name
    End Method


    Method X:Int()
        Return GetGNetInt (GObj, G_X)
    End Method


    Method Name:String()
        Return GetGNetString (GObj, G_NAME)
    End Method


End Type

Local InputName:String = Input("What is your name")
Global MePlayer:TPlayer = TPlayer.CreateMe(InputName)


Repeat
   TPlayer.Check
   CheckNewMembers
   Delay 1000
Until AppTerminate()

Function CheckNewMembers()
    Local NewMembers:TList = GNetObjects(Host, &GNET_CREATED)
    For local obj:TGNetObjects = EachIn NewMembers
       TPlayer.AddOther obj
    Next
End Function
...back from Egypt

Midimaster

#5
Quote from: William on July 13, 2023, 01:12:28Roadbump unable to access a type instance defined or created within a for loop as it is not global or something.

..
For Local obj:TGNetObject=EachIn GNetObjects( host,GNET_ALL )
   global example1:TPlayer = New TPlayer
   ...
   SetGNetFloat LocalPlayer,GNET_PLAYER_X,example1.x

Next
Print example1.x


the bad mistake:
You create the global variable example1 as a new empty TPlayer user-variable inside the For/Next loop.
So it's X and Y properties are also empty. To send them to the SetGnetFloat makes no sense!

not important side effect:
The error appears because you create the example1 as GLOBAL inside the for next loop. To define a Global inside a for /next loop means, that the variable is singular and "global" as long as the For/Next-loop exists. But after the loop is left, the variable is dead !
So the example1  is only known (lives only) inside the For/Next loop. PRINT (which is outside) fails because it does not know a variable example1
...back from Egypt

William

#6
well thats bunk. how do i create a player instance tplayer of each player network object and still be accessible outside the loop for other purposes or will i need to.
im still interested in oldschool app/gamedev

Midimaster

...back from Egypt

William

#8
not sure the best way to implement some openb3d entity functions for the player, i have needed to put the local client player with tplayer


but it seems like a spaghetti code

within the type definition tplayer addme function
    Function Addme:TPlayer(Name:String)
        Local loc:TPlayer = New TPlayer

ScaleEntity loc.playerentity,1,1,1
EntityType(pivot,GroupCharacters)
EntityRadius(pivot, 0.00000000001,0.00000000001)

EntityParent loc.playerentity, Pivot
RotateEntity(loc.playerentity, 180,0,180)

        loc.GObj = CreateGNetObject(Host)
        all.AddLast loc
        Return loc
    End Function

also a new bug, occasionally when i move near the edge of the terrain the player falls below the terrain but not past the edge of the terrain. it does not happen every time though.
im still interested in oldschool app/gamedev

Midimaster

#9
normaly a Entity needs to be a little bit above the terrain. Only in this case the collision automatic can adjust the Entity (when the terrain distance changed). When you move a Entity ahead it can happen, that the new position is temporary below the terrain. In this case the automatic cannot adjust the player anymore and let him fall.

This is the reason, why we need Pivots. The Pivot can move with a clear distance to the ground and gets controled by the automatic. And so it never can get below the ground. The player is a child of the pivot and here you can adjust the optical distance, so that it looks like the player is a little bit "inside" the ground.

The senstive area of entities need to have a minimum size to report collisions and to get the automatic working correct. Why do you scale the pivot's EntityRadius to 0.00000000001. This maybe the reason for the wrong collision result.

Also often a reason: The Entity position was moved several times without giving the collosion check a chance to control every step.

A possible solution: You can calculate the distance Entity-Terrain manually and if the worst case happend you can move the entity upwards. Use

 TerrainY(  pivot.EntityX() , pivot.EntityY() , pivot.EntityZ() )

to find out the terrain height below the pivot
 
...back from Egypt

William

#10
alright the player class looks like spaghetti code i need to figure out how i can work player networking object orientated


ty midimaster its just that i am not learning anything to do myself.

here it is >>:
Type TPlayer

Global all:TList = New TList

Field Username:String
Field x: Float
Field y: Float
Field PlayerIsOnGround:Int
Field YAcceleration:Float
Field playerentity:TEntity = CopyEntity(Playermodel)

    Field GObj:TGNetObject

    Function Addme:TPlayer(Name:String)
        Local loc:TPlayer = New TPlayer

ScaleEntity loc.playerentity,1,1,1
EntityType(pivot,GroupCharacters)
EntityRadius(pivot, 0.00000000002,0.00000000002)

EntityParent loc.playerentity, Pivot
RotateEntity(loc.playerentity, 180,0,180)

        loc.GObj = CreateGNetObject(Host)
        all.AddLast loc
        Return loc
    End Function

    Function Addplayer(Obj:TGNetObject)
        Local loc:TPlayer = New TPlayer
'ShowEntity(loc.playerentity)
        loc.GObj = Obj
        All.AddLast loc
    End Function
End Type

Function ScanGnet()
    ' find new
    For Local obj:TGNetObject=EachIn GNetObjects( host, GNET_CREATED )
If obj = localplayer.GObj
Else
       TPlayer.Addplayer obj
EndIf
    Next
    DrawText "TPlayers:" + TPlayer.All.Count() , 30,130
End Function

so.. i think it can be done `with oop ive seen it before but that i am not sure to do it myself. something like refracting to pass creategnetobject and passing it to addplayer (addothers)  adding a new tplayer type definition so that since it is a new object GNET_CREATED doesnt duplicate create tplayer type definition class. midimaster i am not sure if this makes sense to you, presently with the above code a player tplayer is created twice for this single client.
im still interested in oldschool app/gamedev

Midimaster

There is no need to check for  this check:

If obj = localplayer.GObj
...because the function...
GNetObjects( host, GNET_CREATED )
...with the attribut GNET_CREATED does never report your own localplayer, but only foreign ones!

...back from Egypt

William

#12
then why the result is 2 player entities ingame for 1 client that spawn via 2 tplayer type instances? sorry i realize that may not be with the tutorial example, perhaps i need to look at that more thoroughly
im still interested in oldschool app/gamedev

Midimaster

#13
To make us able to help you, we need access to the current version of the code. If you opened a GitHub-account for the code, you should make sure, that the code there is always up-to-date. I tried to look at your code 2 days ago, when you reported a issue. But I realized, that the last update was 2 month ago.

I read again your last question...

"then why the result is 2 player entities ingame for 1 client that spawn via 2 tplayer type instances?"

... and if I understand it well, I guess: This is normal!

You start the first app it becomes "the server". This raises also the first player (PLAYER 1). The so called server works "under-the-hood" of PLAYER 1.

After this you start the second app. This becomes "a client", but raises the next player (PLAYER 2).

So, when 2 apps are running you should count 2 TPlayers in the TPlayer list ALL. And there are 2 instances in the list GNetObjects( host, GNET_ALL )

...back from Egypt

William

Github has been updated.
im still interested in oldschool app/gamedev