I created NPCs that move that direction you're standing at the moment. If they touch something, they never will move again. I don't have a clue and already wasted like 6 hours searching the fault.
That is my Move-Method:
Overrides Sub Move()
Dim actorPosition As Vector2
Dim spieler As Actor
For Each obj As Actor In Actor.ActorList
If TypeOf obj Is Actor And obj.Alive And obj.ObjektTyp = "A"c Then
actorPosition = obj.position
spieler = obj
End If
Next
Dim difPos As Vector2 = position - actorPosition
normaldifpos = difPos
normaldifpos.Normalize()
If lastTimeAttack + intervallBetweenAttack1 < Game1.Game1Time Then
If difPos.Length < range Then
Select Case ObjektTyp
Case "Z"c
spieler.leben -= stärke
Case "H"c
For Each obj As Objekt In ObjList
If TypeOf obj Is Spells Then
If obj.ObjektTyp = "Z"c And obj.Alive = False Then
obj.position = position
obj.richtung = -normaldifpos
obj.senderE = Me
obj.stärke = stärke
obj.Alive = True
Exit For
End If
End If
Next
End Select
lastTimeAttack = Game1.Game1Time
End If
End If
If difPos.Length() < agroRange Then
If spieler IsNot Nothing And Not collide((normaldifpos + New Vector2(-4, -4) * speed)) Then
position = position - normaldifpos * speed
Else
End If
End If
End Sub
And this my collide method:
Public Overridable Function collide(vek As Vector2) As Boolean
Dim extrahitbox As Rectangle
extrahitbox = Hitbox
extrahitbox.X += vek.X
extrahitbox.Y += vek.Y
For Each obj As Objekt In Objekt.ObjList
If TypeOf obj Is Spells Or TypeOf obj Is Key Or TypeOf obj Is PowerUP Or TypeOf obj Is Coin Then
Else
If extrahitbox.Intersects(obj.Hitbox) Then
Return True
End If
End If
Next
For Each Act As Actor In Actor.ActorList
If Act IsNot Me Then
If extrahitbox.Intersects(Act.Hitbox) Then
Return True
Else
End If
End If
Next
If extrahitbox.X < 0 Then
Return True
ElseIf extrahitbox.Right > 1280 Then
Return True
ElseIf extrahitbox.Top < 0 Then
Return True
ElseIf extrahitbox.Bottom > 720 Then
Return True
End If
End Function
I would appreciate help!
From your example it looks object stuck because once when it collide with other object you are not doing any update to position. After determing collision you have to calculate how deep object is inside other object and move it back to previous position.
One way is after you determinate collision you simply negate velocity.
object.Position -= object.Velocity
object.Velocity = new vector2(0,0)
Other way is more accurate as velocity remain same and if your origin is on top-left position. It collision happened, it will position your object right next to other object depend from where collision happened.
If obj.Intersect(otherObj) Then
Dim newPos as new vector2d = obj.Position
if (obj.velocity.x>0) then newPos.x = otherObj.Left - obj.width
if (obj.velocity.x<0) then newPos.x = otherObj.right
obj.Position = newPos
End If
So basicly goes like this
put position to temp varialbe
check collision
if collision happened set original to temp
draw
Related
I have recently been familiar with lua in LOVE 2D and watched some tutorials and now am trying to make a simple game. The game will feature a character who can run and when pressed 'space', attack(strike with his sword). When pressed 'space', it should go through all the frames/sprites of attacking animation. But the character is not going through all the frames and the interval between them seems really fast even though I kept it minimum.
This is the code I am using to account for the key pressing.
self.animations = {
['idle'] = Animation{
frames = {
self.frames[1]
},
interval = 1
},
['attack'] = Animation{
frames = {
self.frames[1], self.frames[2], self.frames[3], self.frames[4], self.frames[5], self.frames[6], self.frames[3]
},
interval = 0.25
}
}
self.animation = self.animations['idle']
self.currentFrame = self.animation:getCurrentFrame()
self.behaviors = {
['idle'] = function(dt)
if love.keyboard.wasPressed('space') then
self.dy = 0
self.state = 'attack'
self.animation = self.animations['attack']
elseif love.keyboard.wasPressed('up') then
self.dy = -MOVE_DIST
elseif love.keyboard.wasPressed('down') then
self.dy = MOVE_DIST
else
self.dy = 0
end
end,
['attack'] = function(dt)
self.animation = self.animations['attack']
if love.keyboard.wasPressed('up') then
self.dy = -MOVE_DIST
elseif love.keyboard.wasPressed('down') then
self.dy = MOVE_DIST
else
self.dy = 0
self.state = 'idle'
self.animation = self.animations['idle']
end
end
This is my animation class that's responsible for transition effects
Animation = Class{}
function Animation:init(params)
--self.texture = params.texture
self.frames = params.frames
self.interval = params.interval or 0.05
self.timer = 0
self.currentFrame = 1
end
function Animation:getCurrentFrame()
return self.frames[self.currentFrame]
end
function Animation:restart()
self.timer = 0
self.currentFrame = 1
end
function Animation:update(dt)
self.timer = self.timer + dt
if #self.frames == 1 then
return self.currentFrame
else
while self.timer > self.interval do
self.timer = self.timer - self.interval
self.currentFrame = (self.currentFrame + 1) % (#self.frames + 1)
if self.currentFrame == 0 then
self.currentFrame = 1
end
end
end
end
Please help. I hope I asked the question correctly. Thanks in advance.
Don't really know how you deal with the state in the key pressing code but this could be part of the issue too.
Anyway, your Animation:update looks very weird to me and I really think this is the center of the problem. There is a simple function that you could use instead and it should work perfectly (if you have any question about it feel free to ask).
If your not really comfortable with a debugger you could use love.graphics.print to print some value to the screen (like self.currentFrame or self.timer in that case) to see what's going on with those value in real time.
function Animation:update(dt)
self.timer = self.timer + dt/self.interval
if self.timer >= #self.frames then
self.timer = 0
end
self.currentFrame = Math.floor(self.timer)+1
end
Also note that "Math.floor(self.timer)+1" cannot be replaced by "Math.ceil(self.timer)" because it will return 0 if self.timer == 0 (and lua's array starts at one)
Edit:
It could probably come from here:
['attack'] = function(dt)
self.animation = self.animations['attack']
if love.keyboard.wasPressed('up') then
self.dy = -MOVE_DIST
elseif love.keyboard.wasPressed('down') then
self.dy = MOVE_DIST
else
self.dy = 0
self.state = 'idle'
self.animation = self.animations['idle']
end
end
I don't know how you deal with your inputs since 'love.keyboard.wasPressed' if not a love function but if 'up' and 'down' where not pressed the last frame, the state will go back to 'idle' and the animation to animations['idle']
Without more code I cannot do much more for you.
Currently I have 6 images layered over top of each other, each with their own corresponding walk animation frame. Each time you walk the Visible property changes and allows the next animation frame to be seen.
The only problem is the bloody flickering when it is passing through any type of object be it, picturebox, form, command button, etc....
After a tiresome day of research I just can't come up with a solution to fix this.
a little snippet of my code if anyone want's to see:
Select Case CharFrame
Case 1
Avatar(0).Visible = True
Avatar(1).Visible = False
Avatar(2).Visible = False
CharFrame = CharFrame + 1
Case 2
Avatar(0).Visible = False
Avatar(1).Visible = True
Avatar(2).Visible = False
CharFrame = CharFrame + 1
Case 3
Avatar(0).Visible = False
Avatar(1).Visible = False
Avatar(2).Visible = True
CharFrame = 1
End Select
Sleep (Timer)
Avatar(0).Top = Avatar(0).Top + moveY
Avatar(1).Top = Avatar(1).Top + moveY
Avatar(2).Top = Avatar(2).Top + moveY
Avatar(3).Top = Avatar(0).Top
Avatar(4).Top = Avatar(1).Top
Avatar(5).Top = Avatar(2).Top
Avatar(6).Top = Avatar(0).Top
Avatar(7).Top = Avatar(1).Top
Avatar(8).Top = Avatar(2).Top
Avatar(9).Top = Avatar(0).Top
Avatar(10).Top = Avatar(1).Top
Avatar(11).Top = Avatar(2).Top
Loop
Avatar(0).Visible = True
Avatar(1).Visible = False
Avatar(2).Visible = False
Found this with Google:
Private Declare Function LockWindowUpdate Lib "USER32" (ByVal hwndLock As Long) As Long
When you like to stop window updating:
LockWindowUpdate <yourform>.hWnd
If you like to continue
LockWindowUpdate False
Found this, did not try it.
I am following a tutorial that is teaching me about how to make a platformer. In the second tutorial, we started to make a renderer. Whenever I run the code and test the renderer, I get this error
Error: main.lua:24: attempt to index global 'renderer' (a nil value)
I have no idea how to fix it, so here is my code.
renderer.lua
local Renderer = {}
local num_of_layers = 5
local insert = table.insert
local remove = table.remove
function Renderer:create()
local renderer = {}
--
renderer.drawers = {}
for i = 0,num_of_layers do
renderer.drawers[i] = {}
end
--
function renderer:addRenderer(obj, Layer)
local l = layer or 0
insert(self.drawers[l], obj)
end
--
function renderer:draw()
for layer = 0,#self.drawers do
for draw = 0,#self.drawers[layer] do
local obj = self.drawers[layer][draw]
if obj ~= nil then
obj:draw()
end
end
end
end
return renderer
end
--
return Renderer
Here is main.lua
local Renderer = require("libs/renderer")
Renderer = Renderer:create()
function love.load()
love.graphics.setBackgroundColor(255, 255, 255)
--Loading Classes
player_load()
--Loading Classes
end
--
function love.update(dt)
end
--
function love.draw()
renderer:draw()
end
Thanks to everyone who is reading!
Lua is case sensitive.
Renderer = Renderer:create() is not the same as
renderer = Renderer:create()
I am attempting to write a tic-tac-toe game in lua, and plan on using the minimax algorithm to decide non-human moves. The first step in this involves generating a tree of all possible board states from a single input state. I am trying to recursively do this, but cannot seem to figure out how. (I think) I understand conceptually how this should be done, but am having trouble implementing it in lua.
I am trying to structure my tree in the following manner. Each node is a list with two fields.
{ config = {}, children = {} }
Config is a list of integers (0,1,2) that represent empty, X, and O and defines a TTT board state. Children is a list nodes which are all possible board states one move away from the current node.
Here is my function that I currently have to build the game tree
function tree_builder(board, player)
supertemp = {}
for i in ipairs(board.config) do
--iterate through the current board state.
--for each empty location create a new node
--representing a possible board state
if board.config[i] == 0 then
temp = {config = {}, children = {}}
for j in ipairs(board.config) do
temp.config[j] = board.config[j]
end
temp.config[i] = player
temp.children = tree_builder(temp, opposite(player))
supertemp[i] = temp
end
end
return supertemp
end
The function is called in the following manner:
start_board = {config = {1,0,0,0}, children = {} }
start_board.children = tree_builder(start_board, 1)
When I comment out the recursive element of the function (the line "temp.children = builder(temp, opposite(player))") and only generate the first level of children. the output is correct. When called via code that is conceptually identical to (I am using love2D so formatting is different):
for i in pairs(start_board.children) do
print (start_board.children[i].config)
The three children are:
1,1,0,0
1,0,1,0
1,0,0,1
However, once I add the recursive element, the following is output for the same three children
1,1,2,1
1,1,2,1
1,1,2,1
I have been searching online for help and most of what I have found is conceptual in nature or involves implementation in different languages. I believe I have implemented the recursive element wrongly, but cannot wrap my head around the reasons why.
Don't understand what opposite(player) means in temp.children = tree_builder(temp, opposite(player)).
Notice that a recursion need an end condition.
This is my solution under your structure:
local COL = 3
local ROW = 3
local function printBoard( b )
local output = ""
local i = 1
for _,v in ipairs(b.config) do
output = output .. v .. ( (i % COL == 0) and '\n' or ',' )
i = i + 1
end
print( output )
end
local function shallowCopy( t )
local t2 = {}
for k,v in pairs(t) do
t2[k] = v
end
return t2
end
local MAX_STEP = COL * ROW
local ING = 0
local P1 = 1
local P2 = 2
local TIE = 3
local STATUS = { [P1] = "P1 Win", [P2] = "P2 Win", [TIE] = "Tied" }
local start_board = { config = {P1,0,0,0,0,0,0,0,0}, children = {} }
local function checkIfOver( board, step )
local config = board.config
local over = false
--check rows
for i=0,ROW-1 do
over = true
for j=1,COL do
if 0 == config[i*COL+1] or config[i*COL+j] ~= config[i*COL+1] then
over = false
end
end
if over then
return config[i*COL+1]
end
end
--check cols
for i=1,COL do
over = true
for j=0,ROW-1 do
if 0 == config[i] or config[i] ~= config[i+COL*j] then
over = false
end
end
if over then
return config[i]
end
end
--check diagonals
if config[1] ~= 0 and config[1] == config[5] and config[5] == config[9] then
return config[1]
end
if config[3] ~=0 and config[3] == config[5] and config[5] == config[7] then
return config[3]
end
if step >= MAX_STEP then
return TIE
else
return ING
end
end
local function treeBuilder( board, step )
--check the game is over
local over = checkIfOver( board, step )
if over ~= ING then
printBoard( board )
print( STATUS[over], '\n---------\n' )
return
end
local child
local childCfg
for i,v in ipairs(board.config) do
if 0 == v then
child = { config = {}, children = {} }
childCfg = shallowCopy( board.config )
childCfg[i] = (step % 2 == 0) and P1 or P2
child.config = childCfg
table.insert( board.children, child )
treeBuilder( child, step + 1 )
end
end
end
treeBuilder( start_board, 1 )
I have a event listener assigned to an object. This then triggers the startDrag function. I'm moving my character in the game with dragging. But as soon as I scroll or move the display, my dragging function gets all messed up. It doesn't react as it should and the object(event.target) can't be controlled at all.
Did anyone else had this experience?
Is this a corona bug?
How can I solve this?
Can I temporarily disable the startDrag event listener for the time of scrolling? Or maybe restart it?
All help would be greatly appreciated.
Here is the code...
local physics = require( "physics" )
physics.start()
physics.setContinuous( false )
display.setStatusBar( display.HiddenStatusBar )
physics.setScale( 60 )
physics.setDrawMode( "hybrid" )
local height = display.contentHeight
local width = display.contentWidth
local allElements = display.newGroup()
local texsGroup = display.newGroup()
local backGround = display.newRect(0,0-height,width,2*height)
backGround:setFillColor(91,91,91)
backGround:toBack()
local wallBottom = display.newRect(texsGroup, 0,height-20,width,20)
physics.addBody(wallBottom, "static", { density=5, friction=0.5, bounce=0.3 } )
local tex = {}
local numberRips = 60
local texSize = {
-- w: texwidth, h: texheight, s: strength required
{w=30, h=20, s=1},
{w=20, h=10, s=1.5},
{w=10, h=10, s=2},
}
local r
local lim = display.newGroup()
local function createRips()
local originX = 0
local originY = height -75
for i=0,numberRips do
r = math.random(3)
local x = originX + math.random(width)
local y = originY - math.random(2*height)
tex[i] = display.newRect(lim, x, y, texSize[r].w, texSize[r].h)
tex[i].status = "active"
tex[i].size = texSize[r].s
if (r == 1) then
tex[i]:setFillColor(51,255,0)
elseif (r == 2) then
tex[i]:setFillColor(255,51,51)
elseif (r == 3) then
tex[i]:setFillColor(51,51,255)
end
end
end
createRips()
local w, h, r = width/2, height - 265, 12
local L = display.newCircle(w-115,h+29,r)
local buttonRadius = 35
local button3 = display.newCircle((L.x),(L.y),buttonRadius)
button3.myName = "L"
allElements:insert(button3)
allElements:insert(lim)
allElements:insert(L)
local d, f, b = 15, 1, 0.15
physics.addBody(L, "dynamic", { density=d, friction=f, bounce=b, radius=r } )
button3.isVisible = false
button3.isHitTestable = true
physics.addBody( button3, "static", { density=1, radius=buttonRadius } )
local function addFrictionJoint(a, b, posX, posY, lowerAngle, upperAngle, mT)
local j = physics.newJoint ( "pivot", a, b, posX, posY, rFrom, rTo)
j.isLimitEnabled = true
j:setRotationLimits (lowerAngle, upperAngle)
return j
end
-- JOINTS
addFrictionJoint( button3, L, L.x, L.y, 0, 0 )
local function startDrag( event, params )
local body = event.target
local phase = event.phase
local stage = display.getCurrentStage()
local direction = event.direction
if "began" == phase then
stage:setFocus( body, event.id )
body.isFocus = true
event.target.bodyType = "dynamic"
-- Create a temporary touch joint and store it in the object for later reference
if params and params.center then
-- drag the body from its center point
body.tempJoint = physics.newJoint( "touch", body, body.x, body.y )
else
-- drag the body from the point where it was touched
body.tempJoint = physics.newJoint( "touch", body, event.x, event.y )
end
--body.tempJoint.maxForce = 0.25*body.tempJoint.maxForce
-- Apply optional joint parameters
if params then
local maxForce, frequency, dampingRatio
if params.maxForce then
-- Internal default is (1000 * mass), so set this fairly high if setting manually
body.tempJoint.maxForce = params.maxForce
end
if params.frequency then
-- This is the response speed of the elastic joint: higher numbers = less lag/bounce
body.tempJoint.frequency = params.frequency
end
if params.dampingRatio then
-- Possible values: 0 (no damping) to 1.0 (critical damping)
body.tempJoint.dampingRatio = params.dampingRatio
end
end
elseif body.isFocus then
if "moved" == phase then
-- Update the joint to track the touch
body.tempJoint:setTarget( event.x, event.y )
elseif "ended" == phase or "cancelled" == phase then
stage:setFocus( body, nil )
body.isFocus = false
-- Remove the joint when the touch ends
body.tempJoint:removeSelf()
body.bodyType = "static"
end
end
-- Stop further propagation of touch event
return true
end
function moveCamera(e)
if button3.y < -lim.y + 300 then
allElements.y = -(button3.y - 300)
end
end
Runtime:addEventListener("enterFrame", moveCamera)
button3:addEventListener( "touch", startDrag )
When you scroll the screen the touch event and the physics object are in different coordinate systems. See localToContent/globalToContent