Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

In this Discussion

RPG Inventory Pickup + Drop System. Help

edited May 2 in Questions Posts: 124

I’m working on a inventory system for my RPG.
I’m halfway there but need help. Currently when I touch the item added to inventory it leaves a black square, I want it to disappear and a double tap option to drop. Also once a chest is open I want it to show a empty chest, currently it keeps showing the emerald.

displayMode(FULLSCREEN)

function setup()

    Chest:init()
    rectMode(CENTER)
    dir,i=1,1
    delay,xs,ys=0,0,0
    dx,dy=WIDTH/2,HEIGHT/2
    createButtons()

    cx,cy=0,0
    sx,sy=0,0
    dx,dy=0,0

    fill(255)
    stroke(255)
    strokeWidth(1)
    colBody:init()
end

function draw()
    background(40, 40, 50)
    checkButtons()   
    noFill()
    sprite(asset.builtin.Blocks.Glass_Frame,900,100,200,200)
    c1.x=c1.x+dx
    c1.y=c1.y+dy
    sprite(asset.builtin.Planet_Cute.Character_Princess_Girl,c1.x,c1.y)
    chest()
end

function touched(t)
    Chest:touched(t)
    if t.state==BEGAN then
        cx,cy=t.x,t.y      
    end
    if t.state==MOVING then
        if insideCircle(t.x,t.y) then
            dx=(t.x-cx)/10
            dy=(t.y-cy)/10
        else
            cx,cy=0,0
            dx,dy=0,0
        end
    end
    if t.state==ENDED then
        cc,cy=0,0
        dx,dy=0,0
    end
    if t.state==BEGAN or t.state==MOVING then
        for a,b in pairs(bTab) do
            b:touched(t)
        end
    elseif t.state==ENDED then
        xs=0
        ys=0
    end    
end
function collide(c)  -- this gets called when a collision occurs
    Chest:collide(c)
 end
function insideCircle(x,y)
    -- check if touch is inside of circle or ellipse
    a,b=100,100 -- radius of circle or a,b of ellipse
    if (x-cx)^2/a^2+(y-cy)^2/b^2 <= 1 then 
        return true
                    end
                        return false
end

Chest = class()
   inventorypos=vec2

function Chest:init()
    chestClosed=readImage("Planet Cute:Chest Closed")
    chestOpen=readImage("Planet Cute:Chest Open")

    citems={emerald =(asset.builtin.Planet_Cute.Gem_Blue),emerald2 =(asset.builtin.Planet_Cute.Gem_Blue)}
    inventorypos=vec2(950,80)
end

function chest()
    if open then
        sprite(chestOpen,c2.x,c2.y) 
        sprite(citems.emerald,c2.x,c2.y+30)
        r=true
    if ElapsedTime-et>3 then
        open=false
            end
    else
        sprite(chestClosed,c2.x,c2.y)
    end
        if r==true then
           sprite(citems.emerald2,inventorypos.x,inventorypos.y,30,30) 
        else
    end
end

function Chest:touched(t)

        if t.state==BEGAN and t.x>inventorypos.x-50 and t.x<inventorypos.x+50 and t.y>inventorypos.y-50 and t.y<inventorypos.y+50 then  
        citems.emerald2=0
        print("super power actived")
    end
end

function Chest:collide(c)  -- this gets called when a collision occurs
     if c1.x>c2.x-101 and c1.x<c2.x+101 and c1.y>c2.y-101 and c1.y<c2.y+101 then  
        open=true    -- open the chest
        et=ElapsedTime
        end
            end

colBody = class()

function colBody:init()

    physics.gravity(0,0)
    c1 = physics.body(CIRCLE,45)    -- sprite collision circle
    c1.type=DYNAMIC
    c1.x=WIDTH/2
    c1.y=300
    c1.sleepingAllowed=false

    c2 = physics.body(CIRCLE,50)    -- sprite collision circle
    c2.type=STATIC
    c2.x=WIDTH/2
    c2.y=600
    c2.sleepingAllowed=false
end

button=class()

function button:init(x,y,d,xs,ys,n)
    self.x=x    -- x position   
    self.y=y    -- y position
    self.dir=d  -- person direction

    self.xs=xs*4  -- person speed x
    self.ys=ys*4 -- person speed y
    self.name=n -- button name
end

function button:draw()
    fill(255,0,0)
    rect(self.x,self.y,50,50)
    fill(255)
    text(self.name,self.x,self.y)
end

function button:touched(t)
    if t.x>self.x-25 and t.x<self.x+25 and t.y>self.y-25 and t.y<self.y+25 then
        dir=self.dir
        i=dir
        dx=self.xs
        dy=self.ys
    end
end

function createButtons()
    x,y=WIDTH/2,100
    bTab={}
    table.insert(bTab,button(x-50,y+50,17,-1,1,"u-l"))
    table.insert(bTab,button(x,y+50,9,0,1,"up"))
    table.insert(bTab,button(x+50,y+50,1,1,1,"u-r"))
    table.insert(bTab,button(x-50,y,33,-1,0,"left"))
    table.insert(bTab,button(x+50,y,25,1,0,"right"))
    table.insert(bTab,button(x-50,y-50,57,-1,-1,"d-l"))
    table.insert(bTab,button(x,y-50,49,0,-1,"down"))
    table.insert(bTab,button(x+50,y-50,41,1,-1,"d-r"))
end

function checkButtons()
    for a,b in pairs(bTab) do
        b:draw()
    end
end

Comments

  • edited May 3 Posts: 1,726

    See post below for transfer to other thread.

  • Posts: 124

    @Bri_G It works great, thanks! I think you meant to post this in my other forum.

    https://codea.io/talk/discussion/10502/2d-table-tile-map-help#latest
    
  • edited May 2 Posts: 1,726

    @Jarc - yup, sorry transferred it to :smile:

    Scrolling 2D map

  • Posts: 124

    I figured out everything else but can someone tell me why a black square is appearing after I touch the inventory emerald(the small one). I really don’t understanding the logic behind that.

  • Posts: 773
    You set the image to 0 in the chest touch function

    ~~~
    citems.emerald2=0
    ~~~

    The sprite command tries to load a zero image which gives you the black square
  • Posts: 124

    @West Weird, in another example when I collide with a heart sprite it makes the heart sprite = 0, which makes the sprite disappear. Example pics below.
    Why doesn’t that same logic work here.

    Here’s the code to make the heart disappear

    if c.state==BEGAN and
     c1.x>c4.x-100 and c1.x<c4.x+100 and c1.y>c4.y-100 and c1.y<c4.y+100 then
          value=value+10 
            potion[1]=0
            end    
        end
    

    The other difference is the emerald is in the touch function and the heart is in collide function.

  • Posts: 124

    @West nvm it was this line messing me up.

          if r==true then
               sprite(citems[2],inventorypos.x,inventorypos.y,30,30) 
    

    I had to make false but now I have to redo my whole code to get it to work with item dropping :| Does anyone have code for a game inventory equip and drop?
    Or a forum link.

  • edited May 3 Posts: 124

    I’m having one problem with my inventory pick up and drop system, if anyone could help that would nice. My problem is the double tap to drop. Whenever I double tap the empty inventory sprite slot position after opening the chest it drops a emerald. I pretty much want to turn off the touch function so whenever the sprite isn’t in the position(inventory slot) but not sure how to.

    Turn iPad to landscape

    function setup()
        chestClosed=readImage("Planet Cute:Chest Closed")
        chestOpen=readImage("Planet Cute:Chest Open")
    
        tab={readImage(asset.builtin.Planet_Cute.Gem_Blue)}
        tab2={readImage(asset.builtin.Planet_Cute.Gem_Blue)}
        tab3={}
        pos={inv=vec2(850,250),drop=vec2(300,400),chest=vec2(WIDTH/2,HEIGHT/2)}
    end
    
    function draw()
        background(40,40,50)
        sprite(asset.builtin.Blocks.Glass_Frame,900,200,200,200)
        fill(255)
        text("tap screen to open chest for 3 seconds",WIDTH/2,HEIGHT/2+200)
        chest(tab[1],tab2[1])    
    end
    
    function chest(x,z)
        if open then
            sprite(chestOpen,pos.chest.x,pos.chest.y)
            sprite(x,WIDTH/2,HEIGHT/2+70)
        if ElapsedTime-et>3 then
                for a,b in pairs (tab) do
                table.remove(tab,1)
            table.insert(tab,1,0)
                open=false
                    inv=true
                    chestOpen=0
                    chestClosed=0
            end
                end
        else
            sprite(chestClosed,pos.chest.x,pos.chest.y)
            end
        if inv==true and tab[1]==0 then
                sprite(z,pos.inv.x,pos.inv.y,50)
        elseif
            inv==false and tab[1]==0
        then
            sprite(z,pos.drop.x,pos.drop.y,50)
        end
    end
    
    function touched(t)
        if t.state==BEGAN and t.x>pos.chest.x-101 and t.x<pos.chest.x+101 and t.y>pos.chest.y-101 and t.y<pos.chest.y+101 then  
            open=true    -- open the chest
            et=ElapsedTime    -- set time
        end
    
        if t.state==BEGAN and t.x>pos.inv.x-50 and t.x<pos.inv.x+50 and t.y>pos.inv.y-50 and t.y<pos.inv.y+50 and   t.tapCount==1 and inv==true then 
            table.move(tab2,1,1,1,tab3)
            table.insert(tab2,1,0)
            print("super power activated") 
            inv=false
            end   
    
            if t.state==BEGAN and t.x>pos.inv.x-50 and t.x<pos.inv.x+50 and t.y>pos.inv.y-50 and t.y<pos.inv.y+50 and   t.tapCount==2 and inv==false and tab2[1]==0 then
            table.move(tab3,1,1,1,tab2)
            inv=false
            print("item dropped")
            end   
    
             if t.state==BEGAN and t.x>pos.drop.x-50 and t.x<pos.drop.x+50 and t.y>pos.drop.y-50 and t.y<pos.drop.y+50 and tab[1]==0 then
            inv=true
            end     
    end
    
  • Posts: 124

    Ok, so my last inventory system was trash (probably why no one answered :# ) so I made a better one.
    How come after I get the emerald to add to the inventory I get nil?
    I want the code to check for a open slot then if it’s false it adds the game object to inventory.

    function setup()
    
        inventory={
        isFull={false,false,false,false},
        slots={vec2(200,100),vec2(350,100),vec2(500,100),vec2(650,100)}}
    
        items = {asset.builtin.Blocks.Glass_Frame,
                 asset.builtin.Blocks.Glass_Frame,
                 asset.builtin.Blocks.Glass_Frame,
                 asset.builtin.Blocks.Glass_Frame
                }
    
        gameobject = {asset.builtin.Planet_Cute.Gem_Blue,
                     }
        objectpos = vec2(500,400)
    
    end
    
    function draw()
        background(49)
        for i,v in ipairs(inventory.isFull) do
            if inventory.isFull[i] == false then   
           sprite(items[i],inventory.slots[i].x,inventory.slots[i].y)
                elseif
            inventory.isFull[i] == true then
        while true do
                break
                end
            end
        end
        if a==true then
           invsystem(gameobject[i]) 
        end
    
        sprite(gameobject[1],objectpos.x,objectpos.y,75,130)
    end
    
    function invsystem(i)
            for i,v in ipairs(inventory.slots) do
            if inventory.isFull[i] == false then   
            sprite(gameobject[i],inventory.slots[i].x,inventory.slots[i].y)
                elseif
            inventory.isFull[i] == true then
                print("isFull")
        while true do
                break
                end
            end
        end   
    end
    
    function touched (t)
        if t.state==BEGAN and t.x>objectpos.x-60 and t.x<objectpos.x+60 and t.y>objectpos.y-60 and t.y<objectpos.y+60 then 
            print("test")
            a=true
        end
    end
    
  • Posts: 773

    @Jarc I would suggest setting up a couple of classes, one for the items and one for the inventory (made up of slots). You can then track the position of items and slots and manipulate accordingly. Here’s a short example (hopefully this imports ok - there seems to be an issue with the export, where only the firs tab is exported)



    --# Main -- RPG Inventory -- Use this function to perform your initial setup function setup() mapx,mapy,mapw,maph=300,100,500,500 inventory={} --set up 5 vertical slots for ypos=1,5 do table.insert(inventory,Slot(ypos,WIDTH-250,100+ypos*120)) end itemImage={asset.builtin.Planet_Cute.Gem_Green,asset.builtin.Planet_Cute.Key,asset.builtin.Planet_Cute.Gem_Orange} items={} for i=1,6 do --place 3 random items in the map table.insert(items,Item(i,mapx+math.random(mapw),mapy+math.random(maph),math.random(#itemImage))) end end -- This function gets called once every frame function draw() -- This sets a dark background color background(40, 40, 50) --draw "map" area fill(140, 42, 37) rect(mapx,mapy,mapw,maph) for _,s in pairs(inventory) do s:draw() end for _,i in pairs(items) do i:draw() end end function touched(touch) for _,i in pairs(items) do i:touched(touch) end end --# Slot Slot = class() function Slot:init(id,x,y) self.id=id --variable to track the identity of the slot self.x = x self.y=y self.w=100 self.h=100 self.content=0 --holds the id of the item in this slot; 0 means it is empty end function Slot:draw() stroke(255) strokeWidth(3) noFill() rect(self.x,self.y,self.w,self.h) --hard coded size of 100 x 100 --debug text - print the id of any item in the slot in the corner fill(255) text(self.content,self.x+10,self.y+10) end function Slot:touched(touch) -- Codea does not automatically call this method end --# Item Item = class() function Item:init(id,x,y,kind) -- you can accept and set parameters here self.id=id self.x = x self.y = y self.w=100 --hard coded width and height self.h=100 self.kind=kind --the object type - 1 is an emerald, 2 is a key,3 is an orange gem - match with the itemImage array self.location=0 --stores the slot id of the item when picked up; 0 is the default "map" location, -1 would mean the item is used and is ready to be deleted --could expand to include items being in specific chests. self.selected=false -- flag to see if the object is selected - used to put a highlight reticule around it end function Item:draw() sprite(itemImage[self.kind],self.x,self.y,self.w,self.h) --debug text - print the id of the item fill(0) text(self.id,self.x,self.y) --add a selection reticule if self.selected then tint(255,150+100*math.sin(ElapsedTime*4)) sprite(asset.builtin.Blocks.Glass,self.x,self.y,self.w,self.h) noTint() end end function Item:touched(touch) if touch.x>self.x-self.w/2 and touch.x<self.x+self.w/2 and touch.y>self.y-self.h/2 and touch.y<self.y+self.h/2 then self.selected=true self.x=touch.x self.y=touch.y end if touch.state==ENDED and self.selected then self.selected=false --empty the slot if it was picked up from a slot for i,s in pairs(inventory) do if s.content==self.id then s.content=0 end end if self.x<mapx or self.x>mapx+mapw or self.y<mapy or self.y>mapy+maph then --let go of item outside map so place in a slot local destinationslot=0 local desinationslotarrayposition=0 --find the first available empty slot for i,s in pairs(inventory) do if s.content==0 then destinationslot=s.id desinationslotarrayposition=i break end end --update the slot content and item position and location if destinationslot>0 then self.location=destinationslot self.x=inventory[desinationslotarrayposition].x+inventory[desinationslotarrayposition].w/2 self.y=inventory[desinationslotarrayposition].y+inventory[desinationslotarrayposition].h/2 inventory[desinationslotarrayposition].content=self.id else --if there are no empty slots then put it back in the map sound(asset.downloaded.Game_Sounds_One.Wrong) self.x=mapx+math.random(mapw) self.y=mapy+math.random(maph) self.location=0 end end end end
Sign In or Register to comment.