【问题标题】:Multiple shape detection Smallbasic多种形状检测 Smallbasic
【发布时间】:2018-02-09 01:24:49
【问题描述】:

我想为游戏制作一个可控制的角色,但我不希望地板是一种形状。它将由多种形状组成,并具有不同的 y 和 x 位置。每个形状被称为 rectangle[x][y] x 和 y 范围从 1 到 40 以构成一个 20x20 的网格。我唯一能做到的是一种带有碰撞检测的形状。但我真的很想一次拥有所有的形状,我必须做 1600 种不同的 If 语句还是有更简单的选择?最终的程序希望能够创建关卡,然后能够玩这个关卡,但是我现在只创建了关卡。 下面是使用一种形状的示例重力程序。

GraphicsWindow.Show()

player = Shapes.AddEllipse(10,10)
Shapes.Move(player, 100, 5)
For i = 1 To 2
  rec[i] = Shapes.AddRectangle(100,10)
  Shapes.Move(rec[i], 100*i, 500)
EndFor

GraphicsWindow.MouseDown = OnMouse

main:
  playertop = Shapes.GetTop(player)
  shapetop = Shapes.GetTop(rec[1])

  Sub OnMouse
    Shapes.Move(player, Shapes.GetLeft(player), playertop-5)
    upvel = 0.5
  EndSub


  If playertop+12 > shapetop Then
    upvel = 0
  Else
    upvel = upvel - 0.0004
  EndIf
  Shapes.Move(player, Shapes.GetLeft(player), playertop-upvel)
  Program.Delay(1)
Goto main

到目前为止的代码:https://pastebin.com/mFuy2Prd 提前致谢

【问题讨论】:

    标签: collision-detection game-physics shapes smallbasic


    【解决方案1】:

    这是一个管理多个对象的夸张示例。除了管理多个对象之外,它还展示了一个标准游戏循环的示例,以及如何管理帧。不,您不需要 1600 个 if 语句。您需要的是两个匹配的数组来处理对象的 x 和 y 位置。然后,对于每一帧,您都会运行一个嵌套的 for 循环,其中 -- 每个项目都会与其他项目进行比较。

    'Drift and bounce-- Created by codingCat aka Matthew L. Parets -- No rights reserved as long as no money is earned
    'Demonstrates how to manage multiple moving objects at the same time.
    'Circles are added every few ticks until the frame delay is reduced to zero.
    'As the circles move around they bounce into each other
    '----------------------------------------------------------------------------
    'importCode: ZSK870
    'At the top of your program - Initial Setup
    'Stuff up here only happens once before the main loop
    GraphicsWindow.Show()
    GraphicsWindow.KeyDown = OnKeyDown 'Let winows know our key event is waiting for presses. 
    
    stop = "false"
    pressed = "False" 'No key pressed at the start of the program
    frameRate = 50    'Number of milliseonds each frame (trip through the main program) should take
    ballAdd = Clock.ElapsedMilliseconds 'Note the time for adding new balls
    ballRate = 500 'Add a new ball every half second
    balls[1] = Shapes.AddEllipse(5,5)
    ballsX[1] = GraphicsWindow.Width
    ballsY[1] = Math.GetRandomNumber(GraphicsWindow.Height)
    ballSpdX[ballCnt] = (Math.GetRandomNumber(1000) / 100)-500
    ballSpdY[ballCnt] = (Math.GetRandomNumber(1000) / 100)-500
    ballCnt = 1
    
    '----------------------------------------------------------------------------
    
    'Main Program Loop
    'Repeats continuously until the escape key is pressed
    frameStart = Clock.ElapsedMilliseconds 'note the time to allow for frame pauses
    key = "" 
    While key <> "Escape" 'Keep going until the escape key is pressed
      GetKeyPress()       'Check if a key has been pressed
      MoveTheCircles()     'Update circle automatically
      FrameWait()         'Pause and wait for just a tick
    endwhile
    
    '----------------------------------------------------------------------------
    
    'Program Close Down. Stuff that is down once after the main loop
    
    GraphicsWindow.FontSize = 90
    GraphicsWindow.BrushColor = "Red"
    GraphicsWindow.DrawText(100,GraphicsWindow.Height/3,"Good bye")
    Program.Delay(2000)
    Program.end()
    
    '----------------------------------------------------------------------------
    
    'Events and subroutines.
    'Always at the bottom of your program
    'No code outside of a subroutine allowed below.
    
    Sub GetKeyPress
      'Get key press, processes all user interaction.
      'Key presses are ignored unless the event tells us that a new key has been pressed
      If pressed = "True" Then 'ignore unless the event tells us there was a press       
        key = GraphicsWindow.LastKey  'Movement keys
    
        pressed = "False"
      EndIf
    EndSub
    
    
    Sub MoveTheCircles
    
      If (Clock.ElapsedMilliseconds - ballAdd > ballRate) And stop <> "true" then
        ballCnt = ballCnt + 1
        GraphicsWindow.Title = "Balls = " + ballCnt
        GraphicsWindow.PenColor = GraphicsWindow.GetRandomColor()
        balls[ballCnt] = Shapes.AddEllipse(5,5)
        ballsX[ballCnt] = Math.GetRandomNumber(GraphicsWindow.Width)
        ballsY[ballCnt] = Math.GetRandomNumber(GraphicsWindow.Height)
        ballSpdX[ballCnt] = (Math.GetRandomNumber(200) / 100)-1
        ballSpdY[ballCnt] = (Math.GetRandomNumber(200) / 100)-1
        ballAdd = Clock.ElapsedMilliseconds
      EndIf
      For i = 1 To ballCnt
        ballsX[i] = ballsX[i] + ballSpdX[i]
        ballsY[i] = ballsY[i] + ballSpdY[i]
        If ballsX[i] < 0 or ballsX[i] > graphicswindow.Width Then
          ballSpdX[i] = ballSpdX[i] * -1
        endif
        If ballsY[i] < 0 or ballsY[i] > graphicswindow.Height Then
          ballSpdY[i] = ballSpdY[i] * -1
        endif
        For j = 1 To ballCnt
          If i <> j Then
            If (ballsX[j] > ballsX[i] And  ballsX[j] < ballsX[i]+5 And ballsy[j] > ballsy[i] And  ballsy[j] < ballsy[i]+5) Or (ballsX[j]+5 > ballsX[i] And  ballsX[j]+5 < ballsX[i]+5 And ballsy[j] > ballsy[i] And  ballsy[j] < ballsy[i]+5) or (ballsX[j] > ballsX[i] And  ballsX[j] < ballsX[i]+5 And ballsy[j]+5 > ballsy[i] And  ballsy[j]+5 < ballsy[i]+5) Or (ballsX[j]+5 > ballsX[i] And  ballsX[j]+5 < ballsX[i]+5 And ballsy[j]+5 > ballsy[i] And  ballsy[j]+5 < ballsy[i]+5) Then
              ballSpdX[i] = ballSpdX[i] * -1
            endif
          endif     
        endfor  
        Shapes.Move(balls[i], ballsX[i], ballsY[i])
      endfor
    EndSub  
    
    Sub FrameWait
      in = "false"
      While Clock.ElapsedMilliseconds - frameStart < frameRate
        'Sit here and do nothing until the frame clock has run out.
        'This wait keeps the automatic operations, like moving the ball
        'from running too fast. 
        'This technique is better then using Program.Delay() for two reasons:
        '   1)  The wait time is based on when we started the frame, not
        '        when we ended it. In other words, when one of our trips through
        '        the for loop above takes longer than normal, the delay will be 
        '        reduced, so each frame will be exactly the same length.
        '  2) We have the option (even though we are not using it here) of  
        '        doing some extra processing, such as checking the keyboard. 
        '        With Program.Delay() we are stuck, unable to do anything,
        '       until the  delay is complete.
        in = "true"
      EndWhile
      If in <> "true" Then
        GraphicsWindow.Title = "Stopped -- Balls = " + ballCnt
        stop = "true"
      EndIf
    
      frameStart = Clock.ElapsedMilliseconds 'Start  a new frame.
    EndSub
    
    Sub OnKeyDown
      'Take note of the fact that a key has been pressed. This event is 
      'needed because the GraphicsWindow.lastkey property never
      'clears. Making otherwise impossible to distinguish between
      'multiple presses of the same key
      pressed = "True"
    EndSub
    

    【讨论】:

    • 感谢您的回复,我正在解决此代码以尝试使其达到我的目的,目前我正在努力使用 onkeydown 和 getkeypress 进行移动,因为它没有检测到您的手指何时不在关键。有什么办法可以让键盘控制移动吗?
    • 我已经发布了这个文件,代码为:SNZ366
    • 抱歉延迟回复。答案是肯定的。 Smallbasic 具有按键向上和按键向下事件。此导入代码将向您展示如何串联处理事件:ZSB154
    猜你喜欢
    • 1970-01-01
    • 2017-11-21
    • 1970-01-01
    • 2016-06-01
    • 2021-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-09
    相关资源
    最近更新 更多