R0J0hound's Recent Forum Activity

  • Your example disappeared. It should be reversible, but it’s been a bit so let’s redo it from scratch.

    To setup you’d have four objects: oval0, cur0 on layer0, and oval1 and cur1 on layer1. It shouldn’t matter the scale,rotation or rotation of the objects, layer or layout.

    Now let’s suppose you want the mouse position on an oval on one layer to be mapped to an oval on another. We can do that with four set position actions.

    Cur0: set position to mouse(0).x, mouse(0).y
    
    Cur1: set position to cur0.x-oval0.x, cur0.y-oval0.y
    
    Cur1: set position to (self.x*cos(oval0.angle)+self.y*sin(oval0.angle))/oval0.width*oval1.width, (self.x*cos(oval0.angle+90)+self.y*sin(oval0.angle+90))/oval0.height*oval1.height
    
    Cur1: set position to oval1.x+self.x*cos(oval1.angle)+self.y*cos(oval1.angle+90), oval1.y+self.x*sin(oval1.angle)+self.y*sin(oval1.angle+90)

    It should work mapping from any layer to any other layer. The idea here is we get the xy relative from one oval and then calculate the xy relative to another.

  • I mean chess is kind of like any other game. It’s made up of many simpler steps which can be broken up into even simpler steps.

    Generally I think you’d start with how you want to move the pieces. I find moving them with drag and drop sounds pretty intuitive. When you drop you’d snap it to the nearest square. To make it abide by rules you can instead mark all possible moves of that piece and only let you drop on those spots. Just need to be able to look at squares around the piece and see if they are empty or occupied.

    Consider a pawn. One move would be moving up one if the space is free, or move up two if there two spaces ahead are empty. Then for attacks it can go diagonal left or right if there’s an enemy in those squares. It’s pretty straightforward, you just break it down for each piece’s moves.

    The way you implement that can vary a lot. Since it’s a 8x8 grid an array works well but you’d also need to maintain a visual version of that. Using a tilemap mixes array with a visual but you are limited to positions at grid positions. Finally just using sprites for everything gives more position options but you’d have to deal with collisions or picking to inspect squares. Plus you will have to deal with the case of picking two instances of the same type at once I suppose. Anyways, you have options and there are pros and cons of each.

    To see if the king is in check one thing you could do is loop over all the enemy pieces and mark the squares they can attack. If your king is on any of those it’s in check. You can use that to limit where the king moves to so it’s not in check too. But to check if moving another piece will put the king in check you’d just have run the test after the move. And undo it if need be.

    For ai it’s useful to be able to make copies of the game board and try out different moves. So that can add another level of complexity. And as far as how you’d make the ai work it could be as simple as picking random pieces and moves or something more clever and involved. It’s a broad topic and seems involved to make one that isn’t easy to beat.

    Could be educational to try to implement tic-tac-toe, checkers or fox and geese first to get the feel of making a game like chess.

    Beginners tend to write logic like that in a long way. It can be correct but can be tedious to write and refactor. The more you do the more you can use shortcuts like loops, functions and such to reuse code so things aren’t so repetitive.

    Anyways. Interesting idea if you want to make alternate rules. But since it’s intended as a sub game I’d try to find ways to cut as many corners as possible to reduce the time you’d spend on it.

    EDIT:

    Every approach will be a bit different but here is one wip idea how to go about it with a few pieces implemented.

    dropbox.com/scl/fi/260ne0mq2ponctl8rmm6g/chess_wip.capx

    Here's another old one from 2014. It's always interesting to see different approaches. Here it looks like I used arrays more and got it to detect if the kings were in check, but I don't find it very readable.

    dropbox.com/scl/fi/wzw1iy1ng75ijdl26pfl3/chess.capx

  • Here's a demonstration of the hybrid approach. Basically it sets the animation from the angle of motion unless moving diagonally. When moving diagonally it keeps using the direction of whichever arrow key was pressed first. There are likely other ways to implement the idea.

    dropbox.com/scl/fi/tnk06c4xrpkfms75w3b7y/topdown_control_and_animation.capx

  • A hybrid approach may be what he’s after. Use angle of motion in most cases, but when moving at a 45 favor the direction pressed first. That or I’m completely misreading what he’s after.

    Global number jx=0
    Global number jy=0
    Global text keys=“”
    
    On left pressed
    — add -1 to jx
    — add “L” to keys
    
    On left released
    — add 1 to jx
    — set Keyes to replace(keys, “L”, “”)
    
    On right pressed
    — add 1 to jx
    — add “R” to keys
    
    On right released
    — add -1 to jx
    — set Keyes to replace(keys, “R”, “”)
    
    …etc for other keys 
    
    Compare: abs(jx)+abs(jy) = 0
    — set anim to “idle”
    
    Else
    Compare: abs(jx)+abs(jy) = 1
    — set anim to tokenat(“right,down,left,up”, (angle(0,0,jx,jy)+360)%360/90,”,”)
    
    Else
    — set anim to tokenat(“right,down,left,up”, find(“RDLU”,left(keys,1)),”,”)

    Or maybe there’s a simpler way.

  • Here's an example of the idea above. Opted to use the next tree's x position and size as inputs, and made the hidden layer have three nodes. Seems to generally converge on a decent ai player by 10 generations. Jumping so it just misses the back corner seems to be the way to go.

    dropbox.com/scl/fi/jhhtxm6eunyqaqsm46qsv/neuralNetwork.capx

    I'm not sure if this is valuable to anyone but myself, but I can see possibly using it for other games.

    I found smaller NNs converge faster and it helps to have repeatable levels, at least at first. After mastering a premade level you can throw random generation at it. I also found that giving it simpler goals first helps as well. I'm probably only scratching the surface, as there are a lot of other ideas that come to mind.

  • That plug-in looks to be for a specific kind of neural network. You provide inputs and use some training data with the output to tune the weights with the back propagation action.

    For what you want the “deep” basically means taking the pixels of the game screen and using that as an input. Likely applying some convolution to reduce the amount of data first. You may be better off just feeding the NN with inputs directly to simplify things. Probably the x positions of the next three obstacles or something. The output would be whether to jump or not.

    For the “reenforcement learning” that would basically mean running the game multiple times with random weights, then taking the ones that performed the best and run copies of that with slight differences with the weights and repeat. Over time it would converge on a better solution.

    Anyways that’s what I gather from reading on it. Looks to be a vast subject and there is a lot of ideas you can implement.

    Anyways, as a simple example, you could have the x of the two next platforms be the input, and have a hidden layer of two nodes, and an output of one node of whether to jump or not.

    Math wise you can calculate whether to jump with the NN like so.

    In0 = tree.x
    In1 = tree.x
    Hidden0 = 1/(1+exp(-(in0*w0+in1*w1+w2)))
    Hidden1 = 1/(1+exp(-(in0*w3+in1*w4+w5)))
    Jump = 1/(1+exp(-(hidden0*w6+hidden1*w7+w8)))

    You’d need to do some picking so the inputs would be the next two trees. Or if there isn’t any you could set the values to infinity or something.

    The w0 through w8 values is an array of 9 values that make up the brains of your NN. the values apparently are usually in the 0 to 1 range. Initially you’d just use random values and you’d choose one of them to tweak to do a mutation.

    By having the 9 weights in one array it’s easy to duplicate it to make variations. You could even store the distance as instance variables.

    Game loop would be to take one of the arrays, duplicate it and tweak some values of the duplicates. Then run the game with each of them until the player dies and log the distance. Once they are all done keep the best, remove the others and repeat.

    There are likely other improvements but that’s the limit of my knowledge at the moment. It’s likely easier to do better or more advanced things by understanding neural networks better.

    This guy has good videos explaining stuff like that. But you may want written docs at some point.

    m.youtube.com/channel/UCYO_jab_esuFRV4b17AJtAw

  • When moving diagonally the x/y speed is slower but the total speed is equal to the max speed which is what most games want. Otherwise you’d actually be moving faster on a diagonal.

    Anyways, I guess one solution would be to give your object two 8direction behaviors. Set one the up and down and the other to left and right and you’ll be set.

    You could even skip the behaviors altogether and just do some events like:

    Key left is down
    — sprite: move self.speed*dt pixels at angle 180
    Key right is down
    — sprite: move self.speed*dt pixels at angle 0
    …etc for up and down

    As to the animation issue, I suppose you could solve that by somehow keeping track of the order the keys were pressed. I’m thinking you could do it with an array that you’d add the key to the end of when you press a key, and you remove the key from the array when you release it. Then you’d just play the animation of the key in index 0 of the array. It’s simple enough you can get away with implementing it with a text variable instead if you wanted like so:

    global text keys=“”
    
    On left pressed
    — add “L” to keys
    
    On left released
    — set keys to replace(keys, “L”, “”)
    
    On right pressed
    — add “R” to keys
    
    On right released
    — set keys to replace(keys, “R”, “”)
    
    Compare: left(keys,1) = “R”
    — set animation to “right”
    
    Compare: left(keys,1) = “L”
    — set animation to “left”

    That should get the idea across. Adding up and down can be added too with minimal effort.

  • Found him. Must be on vacation?

  • Enums are just numbers under the hood but I can see the value of ensuring that only a certain set of values are used. You could use a function to set the values with events and do the checks there if you really wanted to.

    As for using array.asJson, if you look at the manual you can access the array object directly from JavaScript instead of having to pass the json back and forth.

    Personally the hoops needed to jump between programming languages is annoying enough that I try to avoid it completely. Events only in construct and if I want to use JavaScript I just don’t use construct at all.

    The exception is for performance. Same algorithm in events vs js can be x10 faster in js in some cases. So I’ve done that sometimes. I personally think there’s no reason events can’t be made to perform nigh as fast as JavaScript with some internals reworking. But I’d rather not worry about something I have no control over.

  • It’s mainly useful to interact with other js/ts libraries if you don’t want to deal with making a plugin. Although plugins/behaviors are simpler to use for end users and provide some deeper hooks into the engine.

    It’s also a nice advertisement point for Construct and attracts some users that don’t like visual coding or look at it as a way to dabble in coding along with events.

    JavaScript/typescript code can perform better than events for more algorithmic stuff but it really depends on what you’re doing.

    There are pros and cons of course. Cons off hand are you have to deal with more boiler plate code to interact with the api, debugging is more involved, and you’re kinda thrown out there dealing with how those languages work. Construct can only help so much with that.

    Overall events and typed code have their own workflows and it mostly comes down to personal preference. Pick your poison. They all have their annoyances when trying to implement some logic.

  • Try Construct 3

    Develop games in your browser. Powerful, performant & highly capable.

    Try Now Construct 3 users don't see these ads
  • Forum is pretty inactive and probably few have suggestions. You can only say you’re being ignored if it’s someone’s job to answer questions I think.

    Anyways, the enemies stop moving since you’re only moving to the first node of the calculated path. You’ll probably want to have it move to each node one by one, and once the enemy is close enough to one node move to the next.

    As for the floaty movement you’d need to calculate different forces to do that. A force to a position generally is always floaty. Intuitively a force perpendicular to the velocity should help it turn faster.

    Or you may be able to throw some math at it to calculate the force required to change the current velocity to another one in one frame.

    Force = K*(TargetVelocity-currentVelocity)*mass*60

    Or split into xy components:

    Forcex=k*(targetvx-currentvx)*mass*60

    Forcey=k*(targetvx-currentvy)*mass*60

    Where k controls how rigid it works. 1 means the velocity changes in one frame, and 0.5 would make it a bit floatier.

    The target velocity would be something like:

    A=angle(enemy.x,enemy.y,node.x,node.y)

    Targetvx=speed*cos(a)

    Targetvy=speed*sin(a)

    You could also try limiting the velocity or force as well. In general you can limit xy values with:

    Mag=distance(0,0,x,y)

    If mag>limit

    — set x to x/mag*limit

    — set y to y/mag*limit

    Anyways, just some ideas.

  • You can incorporate time delta (dt). Basically rate*time=distance.

    Your growth rate is 1 pixel per 1/120th of a second or 1/1/120 which is 120.

    That would basically look like this in events:

    midi: key is down
    — 9patch: set height to self.height+120*dt