1.3.1 Update - Move files to new locations, parameter count increased to 5.
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
[IDEal Project file]
|
||||
<Settings>
|
||||
Version="1"
|
||||
Expanded="True"
|
||||
Icon=""
|
||||
MainFile="Example07.bb"
|
||||
Compiler="Blitz3D"
|
||||
CommandLine=""
|
||||
</Settings>
|
||||
<Folders>
|
||||
</Folders>
|
||||
<Files>
|
||||
AbsPath="\Example01.bb" PrjFolder="" Line="0" Column="0" Tip="0" Visible="False"
|
||||
AbsPath="\Example02.bb" PrjFolder="" Line="0" Column="0" Tip="0" Visible="False"
|
||||
AbsPath="\Example03.bb" PrjFolder="" Line="0" Column="0" Tip="0" Visible="False"
|
||||
AbsPath="\Example04.bb" PrjFolder="" Line="0" Column="0" Tip="0" Visible="False"
|
||||
AbsPath="\Example05.bb" PrjFolder="" Line="0" Column="0" Tip="0" Visible="False"
|
||||
AbsPath="\Example06.bb" PrjFolder="" Line="0" Column="0" Tip="0" Visible="False"
|
||||
AbsPath="\Example07.bb" PrjFolder="" Line="0" Column="0" Tip="0" Visible="False"
|
||||
AbsPath="\Example_Shared.bb" PrjFolder="" Line="0" Column="0" Tip="0" Visible="False"
|
||||
</Files>
|
||||
@@ -0,0 +1,72 @@
|
||||
; BlitzPointer - Adding Pointers to Blitz.
|
||||
; Copyright (C) 2015 Project Kube (Michael Fabian Dirks)
|
||||
;
|
||||
; This program is free software: you can redistribute it and/or modify
|
||||
; it under the terms of the GNU Lesser General Public License as
|
||||
; published by the Free Software Foundation, either version 3 of the
|
||||
; License, or (at your option) any later version.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU Lesser General Public License
|
||||
; along with this program. If not, see <http:;www.gnu.org/licenses/>.
|
||||
|
||||
; ---------------------------------------------------------------------------- ;
|
||||
; Example 1 - Retrieving Function Pointers
|
||||
; ---------------------------------------------------------------------------- ;
|
||||
; License: Creative Commons Attribution 2.0
|
||||
; Author: Michael Fabian Dirks<michael.dirks@realitybends.de>
|
||||
|
||||
; If you don't know what a pointer is, I recommend googling it.
|
||||
|
||||
; Blitz doesn't offer native ways of getting function pointers, nor would they
|
||||
; work with anything but tailored ASM calls. So what can they be useful for?
|
||||
; Here are some examples on what you can do:
|
||||
; * Footprint-only Callbacks (no longer need to override functions)
|
||||
; * Creating APIs that support multiple versions.
|
||||
|
||||
|
||||
Include "Example_Shared.bb"
|
||||
ExampleInit()
|
||||
|
||||
; We begin by initalizing a variable to hold our pointer. Globals work best for
|
||||
; this task as we don't have to use a function parameter.
|
||||
Global fpOurFunction = 0
|
||||
|
||||
; Our function can be anything we want, however we must be able to call it once
|
||||
; without effect before we can actually retrieve the function pointer. Why?
|
||||
; Simple! The BP_GetFunctionPointer traces the return address for the
|
||||
; Blitz function signature - and thus can't work outside a function.
|
||||
Function OurFunction()
|
||||
; Let's begin by checking if we already have the pointer. Not required, but
|
||||
; we do it anyway to save some scanning time on every call.
|
||||
If fpOurFunction = 0 Then
|
||||
; Now let us call the above mentioned function to retrieve the pointer.
|
||||
fpOurFunction = BP_GetFunctionPointer()
|
||||
; Weether you use a Return or an Else is up to you. Return is technically
|
||||
; faster in Blitz, as using Else causes a complex ASM construction.
|
||||
Return
|
||||
EndIf
|
||||
|
||||
; For proof reasons, we show the pointer on the screen.
|
||||
Text 0, 0, "Function Pointer"
|
||||
Text 0,15, " 0x" + Replace(RSet(Hex(fpOurFunction),8)," ","0")
|
||||
End Function
|
||||
; Now we call our function once. Since there is no function pointer assigned
|
||||
; it will return almost immediately.
|
||||
OurFunction()
|
||||
|
||||
While Not KeyHit(1)
|
||||
ExampleUpdate()
|
||||
|
||||
OurFunction()
|
||||
|
||||
ExampleLoop()
|
||||
Wend
|
||||
|
||||
End
|
||||
;~IDEal Editor Parameters:
|
||||
;~C#Blitz3D
|
||||
@@ -0,0 +1,58 @@
|
||||
; BlitzPointer - Adding Pointers to Blitz.
|
||||
; Copyright (C) 2015 Project Kube (Michael Fabian Dirks)
|
||||
;
|
||||
; This program is free software: you can redistribute it and/or modify
|
||||
; it under the terms of the GNU Lesser General Public License as
|
||||
; published by the Free Software Foundation, either version 3 of the
|
||||
; License, or (at your option) any later version.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU Lesser General Public License
|
||||
; along with this program. If not, see <http:;www.gnu.org/licenses/>.
|
||||
|
||||
; ---------------------------------------------------------------------------- ;
|
||||
; Example 2 - Calling Functions (Beginner)
|
||||
; ---------------------------------------------------------------------------- ;
|
||||
; License: Creative Commons Attribution 2.0
|
||||
; Author: Michael Fabian Dirks<michael.dirks@realitybends.de>
|
||||
; Prerequisite: Example 1
|
||||
|
||||
; Since we now know how to retrieve a function pointer, how about we call it?
|
||||
|
||||
Include "Example_Shared.bb"
|
||||
ExampleInit()
|
||||
|
||||
Global fpOurFunction = 0
|
||||
Function OurFunction()
|
||||
If fpOurFunction = 0 Then
|
||||
fpOurFunction = BP_GetFunctionPointer()
|
||||
Return
|
||||
EndIf
|
||||
|
||||
Text 0, 0, "Function Pointer"
|
||||
Text 0,15, " 0x" + Replace(RSet(Hex(fpOurFunction),8)," ","0")
|
||||
End Function
|
||||
OurFunction()
|
||||
|
||||
While Not KeyHit(1)
|
||||
ExampleUpdate()
|
||||
|
||||
; BlitzPointer offers many ways of calling our function pointer. Each one
|
||||
; describes different return types, parameter count and parameter types.
|
||||
; Let's use the one that doesn't return a value for now.
|
||||
BP_CallFunctionV fpOurFunction
|
||||
; Now if we run the program, instead of a fixed native call, we're calling a
|
||||
; function pointer instead. Pretty useful in my opinion, especially for UI,
|
||||
; networking, fake classes, etc.
|
||||
; We'll talk about the other ways of calling a function in Example 3.
|
||||
|
||||
ExampleLoop()
|
||||
Wend
|
||||
|
||||
End
|
||||
;~IDEal Editor Parameters:
|
||||
;~C#Blitz3D
|
||||
@@ -0,0 +1,89 @@
|
||||
; BlitzPointer - Adding Pointers to Blitz.
|
||||
; Copyright (C) 2015 Project Kube (Michael Fabian Dirks)
|
||||
;
|
||||
; This program is free software: you can redistribute it and/or modify
|
||||
; it under the terms of the GNU Lesser General Public License as
|
||||
; published by the Free Software Foundation, either version 3 of the
|
||||
; License, or (at your option) any later version.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU Lesser General Public License
|
||||
; along with this program. If not, see <http:;www.gnu.org/licenses/>.
|
||||
|
||||
; ---------------------------------------------------------------------------- ;
|
||||
; Example 3 - Calling Functions (Intermediate)
|
||||
; ---------------------------------------------------------------------------- ;
|
||||
; License: Creative Commons Attribution 2.0
|
||||
; Author: Michael Fabian Dirks<michael.dirks@realitybends.de>
|
||||
; Prerequisite: Example 2
|
||||
|
||||
; BlitzPointer offers a lot of ways to call our function pointer. Each one
|
||||
; describes return type, parameter count and parameter types.
|
||||
; So, what magic can we do with those?
|
||||
|
||||
; BlitzPointer supports three return types:
|
||||
; ---------------------------------------------------------------------------- ;
|
||||
; Type Id Description Calling Function
|
||||
; ---------------------------------------------------------------------------- ;
|
||||
; void V Nothing BP_CallFunctionV
|
||||
; int I 32-bit Integer BP_CallFunctionI
|
||||
; float F Floating Point BP_CallFunctionF
|
||||
|
||||
; Now that we know what we can and can't do (without memory leaks at least),
|
||||
; let's try out the return types ourselves.
|
||||
|
||||
Include "Example_Shared.bb"
|
||||
ExampleInit()
|
||||
|
||||
; 'void' function
|
||||
Global fpVoidFunction = 0
|
||||
Function VoidFunction()
|
||||
If fpVoidFunction = 0 Then
|
||||
fpVoidFunction = BP_GetFunctionPointer()
|
||||
Return
|
||||
EndIf
|
||||
Text 0, 0, "Void Return Type"
|
||||
End Function
|
||||
VoidFunction()
|
||||
|
||||
; 'int' function
|
||||
Global fpIntFunction = 0
|
||||
Function IntFunction%()
|
||||
If fpIntFunction = 0 Then
|
||||
fpIntFunction = BP_GetFunctionPointer()
|
||||
Return
|
||||
EndIf
|
||||
Text 0, 15, "Int Return Type"
|
||||
Return MilliSecs()
|
||||
End Function
|
||||
IntFunction()
|
||||
|
||||
; 'float' function
|
||||
Global fpFloatFunction = 0
|
||||
Function FloatFunction#()
|
||||
If fpFloatFunction = 0 Then
|
||||
fpFloatFunction = BP_GetFunctionPointer()
|
||||
Return
|
||||
EndIf
|
||||
Text 0, 30, "Float Return Type"
|
||||
Return MilliSecs() / 1000.0
|
||||
End Function
|
||||
FloatFunction()
|
||||
|
||||
While Not KeyHit(1)
|
||||
ExampleUpdate()
|
||||
|
||||
; Calling the function and using the return value is really easy to do now:
|
||||
BP_CallFunctionV(fpVoidFunction) ; void returns nothing.
|
||||
Text 200, 15, BP_CallFunctionI(fpIntFunction)
|
||||
Text 200, 30, BP_CallFunctionF(fpFloatFunction)
|
||||
|
||||
ExampleLoop()
|
||||
Wend
|
||||
End
|
||||
;~IDEal Editor Parameters:
|
||||
;~C#Blitz3D
|
||||
@@ -0,0 +1,128 @@
|
||||
; BlitzPointer - Adding Pointers to Blitz.
|
||||
; Copyright (C) 2015 Project Kube (Michael Fabian Dirks)
|
||||
;
|
||||
; This program is free software: you can redistribute it and/or modify
|
||||
; it under the terms of the GNU Lesser General Public License as
|
||||
; published by the Free Software Foundation, either version 3 of the
|
||||
; License, or (at your option) any later version.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU Lesser General Public License
|
||||
; along with this program. If not, see <http:;www.gnu.org/licenses/>.
|
||||
|
||||
; ---------------------------------------------------------------------------- ;
|
||||
; Example 4 - Calling Functions (Advanced)
|
||||
; ---------------------------------------------------------------------------- ;
|
||||
; License: Creative Commons Attribution 2.0
|
||||
; Author: Michael Fabian Dirks<michael.dirks@realitybends.de>
|
||||
; Prerequisite: Example 3
|
||||
|
||||
; Returned values aren't everything, don't you agree? That is why BlitzPointer
|
||||
; offers you the ability to pass parameters too, even allowing you to pass Type
|
||||
; Objects without having to use Handle() and Object() (both slow functions).
|
||||
; At the time of writing this example, BlitzPointer supports four parameters at
|
||||
; most - plenty of space to pass type objects and variables on.
|
||||
|
||||
; There are three parameter types in Blitz that we can use:
|
||||
; ---------------------------------------------------------------------------- ;
|
||||
; Type Id Description Calling Function
|
||||
; ---------------------------------------------------------------------------- ;
|
||||
; int I 32-bit Integer BP_CallFunction*I
|
||||
; float F Floating Point BP_CallFunction*F
|
||||
; pointer P Memory Pointer BP_CallFunction*P
|
||||
|
||||
; Watch out:
|
||||
; Calling a function that has parameters without giving enough parameters will
|
||||
; fill those parameters with values that have been on the stack (and possibly
|
||||
; corrupt the stack too - you never know).
|
||||
|
||||
Include "Example_Shared.bb"
|
||||
ExampleInit()
|
||||
|
||||
; Example Function: Divide p1 by 60 and return the result.
|
||||
Global fpCurInGameSecond = 0
|
||||
Function CurInGameSecond%(p1%=0)
|
||||
If fpCurInGameSecond = 0 Then
|
||||
fpCurInGameSecond = BP_GetFunctionPointer()
|
||||
Return
|
||||
EndIf
|
||||
Text 5, 15, "IIFunction"
|
||||
Text 125, 15, p1
|
||||
|
||||
Return (p1 Shr 2) / 15 ; Division by 60
|
||||
End Function
|
||||
CurInGameSecond()
|
||||
|
||||
; Example Function: Multiply p1 by p2 and return the result.
|
||||
Global fpCurInGameSecondEx = 0
|
||||
Function CurInGameSecondEx#(p1%=0, p2#=0)
|
||||
If fpCurInGameSecondEx = 0 Then
|
||||
fpCurInGameSecondEx = BP_GetFunctionPointer()
|
||||
Return
|
||||
EndIf
|
||||
|
||||
Text 5, 30, "FIFFunction"
|
||||
Text 125, 30, p1
|
||||
Text 245, 30, p2
|
||||
|
||||
Return p1 * p2
|
||||
End Function
|
||||
CurInGameSecondEx()
|
||||
|
||||
; Example Function: Convert between Float and Int easily
|
||||
; For this to work we must take and return a float.
|
||||
Global fpConvertIntFloat
|
||||
Function ConvertIntFloat#(p1#=0)
|
||||
If fpConvertIntFloat = 0 Then
|
||||
fpConvertIntFloat = BP_GetFunctionPointer()
|
||||
Print Hex(fpConvertIntFloat)
|
||||
WaitKey()
|
||||
Return
|
||||
EndIf
|
||||
|
||||
Return p1
|
||||
End Function
|
||||
ConvertIntFloat()
|
||||
|
||||
; Pointer-parameters are a bit trickier and require memory access, see UserLibs.txt.
|
||||
|
||||
Local Frame% = 0
|
||||
While Not KeyHit(1)
|
||||
ExampleUpdate()
|
||||
|
||||
Text 0, 0, "Functions"
|
||||
Text 120, 0, "Parameter 1"
|
||||
Text 240, 0, "Parameter 2"
|
||||
Text 360, 0, "Parameter 3"
|
||||
Text 480, 0, "Parameter 4"
|
||||
Text 600, 0, "Result"
|
||||
|
||||
Text 605, 15, BP_CallFunctionII(fpCurInGameSecond, Frame)
|
||||
Text 605, 30, BP_CallFunctionFIF(fpCurInGameSecondEx, Frame, 0.016666666)
|
||||
|
||||
Local TempFlt# = Frame / 60.0
|
||||
Local TempInt% = BP_CallFunctionIF(fpConvertIntFloat, TempFlt)
|
||||
Text 5, 60, "Float -> Int"
|
||||
Text 125, 60, TempFlt
|
||||
Text 605, 60, Hex(TempInt)
|
||||
|
||||
Text 5, 75, "Int -> Float"
|
||||
Text 125, 75, Hex(TempInt)
|
||||
Text 605, 75, BP_CallFunctionFI(fpConvertIntFloat, TempInt)
|
||||
|
||||
ExampleLoop()
|
||||
|
||||
; Allow us to pause execution
|
||||
While KeyDown(57)
|
||||
WaitTimer(Example_Timer)
|
||||
Wend
|
||||
|
||||
Frame=Frame+1
|
||||
Wend
|
||||
End
|
||||
;~IDEal Editor Parameters:
|
||||
;~C#Blitz3D
|
||||
@@ -0,0 +1,74 @@
|
||||
; BlitzPointer - Adding Pointers to Blitz.
|
||||
; Copyright (C) 2015 Project Kube (Michael Fabian Dirks)
|
||||
;
|
||||
; This program is free software: you can redistribute it and/or modify
|
||||
; it under the terms of the GNU Lesser General Public License as
|
||||
; published by the Free Software Foundation, either version 3 of the
|
||||
; License, or (at your option) any later version.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU Lesser General Public License
|
||||
; along with this program. If not, see <http:;www.gnu.org/licenses/>.
|
||||
|
||||
; ---------------------------------------------------------------------------- ;
|
||||
; Example 5 - Calling Functions (Advanced)
|
||||
; ---------------------------------------------------------------------------- ;
|
||||
; License: Creative Commons Attribution 2.0
|
||||
; Author: Michael Fabian Dirks<michael.dirks@realitybends.de>
|
||||
; Prerequisite: Example 4
|
||||
|
||||
; In Blitz, there are only three real types: Int, Float and String - anything
|
||||
; else is a pointer that can be represented using Int. That is why almost all
|
||||
; Blitz functions return an Int.
|
||||
; Using this knowledge we can try (and succeed) passing a Type Object into a
|
||||
; function - using nothing more than the Int() function.
|
||||
|
||||
Include "Example_Shared.bb"
|
||||
ExampleInit()
|
||||
|
||||
; We'll have to define a Type that can be passed to our function, any Type will
|
||||
; do fine.
|
||||
Type MyType
|
||||
Field Test
|
||||
Field Name$
|
||||
End Type
|
||||
|
||||
; The function can be defined like any other Blitz function.
|
||||
Global fpMyTypeFunc = 0
|
||||
Function MyTypeFunc(This.MyType)
|
||||
If fpMyTypeFunc = 0 Then
|
||||
fpMyTypeFunc = BP_GetFunctionPointer()
|
||||
Return
|
||||
EndIf
|
||||
If This = Null Then Return
|
||||
|
||||
; Display the content of the Type Object.
|
||||
Text 0, Handle(This) * 15, This\Test + This\Name
|
||||
End Function
|
||||
MyTypeFunc(Null)
|
||||
|
||||
; And create two testing objects.
|
||||
Local MT1.MyType = New MyType
|
||||
MT1\Test = 1
|
||||
MT1\Name = "First Object"
|
||||
|
||||
Local MT2.MyType = New MyType
|
||||
MT2\Name = "Second Object"
|
||||
|
||||
While Not KeyHit(1)
|
||||
ExampleUpdate()
|
||||
|
||||
; Now in order to pass a Type Object to a function, we have to get a pointer
|
||||
; from it. Thankfully, Blitz has this already built in: Int().
|
||||
If KeyDown(2) Then BP_CallFunctionVI fpMyTypeFunc, Int(MT1)
|
||||
If KeyDown(3) Then BP_CallFunctionVI fpMyTypeFunc, Int(MT2)
|
||||
|
||||
ExampleLoop()
|
||||
Wend
|
||||
End
|
||||
;~IDEal Editor Parameters:
|
||||
;~C#Blitz3D
|
||||
@@ -0,0 +1,119 @@
|
||||
; BlitzPointer - Adding Pointers to Blitz.
|
||||
; Copyright (C) 2015 Project Kube (Michael Fabian Dirks)
|
||||
;
|
||||
; This program is free software: you can redistribute it and/or modify
|
||||
; it under the terms of the GNU Lesser General Public License as
|
||||
; published by the Free Software Foundation, either version 3 of the
|
||||
; License, or (at your option) any later version.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU Lesser General Public License
|
||||
; along with this program. If not, see <http:;www.gnu.org/licenses/>.
|
||||
|
||||
; ---------------------------------------------------------------------------- ;
|
||||
; Example 6 - Direct Memory Access
|
||||
; ---------------------------------------------------------------------------- ;
|
||||
; License: Creative Commons Attribution 2.0
|
||||
; Author: Michael Fabian Dirks<michael.dirks@realitybends.de>
|
||||
; Prerequisite: Example 5
|
||||
|
||||
; --!-!!!-!--
|
||||
; This Example is aimed at Experts. You will most likely never need this.
|
||||
; --!-!!!-!--
|
||||
|
||||
; BlitzPointer ships with functions for direct memory access, allowing you to
|
||||
; modify things that were previously out of reach. The functions follow the
|
||||
; typical style of Bank access, Peek and Poke:
|
||||
; PeekMemoryByte%(MemoryAddress%) / PokeMemoryByte(MemoryAddress%, Value%)
|
||||
; PeekMemoryShort%(MemoryAddress%) / PokeMemoryShort(MemoryAddress%, Value%)
|
||||
; PeekMemoryInt%(MemoryAddress%) / PokeMemoryInt(MemoryAddress%, Value%)
|
||||
; PeekMemoryFloat#(MemoryAddress%) / PokeMemoryFloat(MemoryAddress%, Value#)
|
||||
; PeekMemory%(MemoryAddress%, Length%, Bank%) / PokeMemory%(MemoryAddress%, Length%, Bank%)
|
||||
; This function allows you to directly read and write from memory into a Bank
|
||||
; or from a Bank, saving you a few instructions per access. It will only read
|
||||
; or write as many bytes as your Bank holds and returns the amount of read or
|
||||
; written bytes.
|
||||
|
||||
; These allow us to do simple direct memory modification, allowing us to do some
|
||||
; things that were previously only possible using MemMove and MemCopy from
|
||||
; the Windows libraries.
|
||||
|
||||
; For example, Types in Blitz follow this structure:
|
||||
; ---------------------------------------------------------------------------- ;
|
||||
; Offset Type Description
|
||||
; ---------------------------------------------------------------------------- ;
|
||||
; 0 Pointer Pointer to Field Data
|
||||
; 4 Pointer Next Type Object or Type Structure (Last Element Signal)
|
||||
; 8 Pointer Prev Type Object or Type Structure (First Element Signal)
|
||||
; 12 Pointer Type Structure
|
||||
; 16 Integer Reference Count
|
||||
; 20+ ... Your Field Data usually follows here.
|
||||
;
|
||||
; We can do some fun stuff with this information.
|
||||
|
||||
; If you want to know more about the internal structure of Blitz, there are some
|
||||
; resources that people have compiled in addition to the official source:
|
||||
; Structures: http://www.blitzforum.de/forum/viewtopic.php?t=4320
|
||||
; Source Code: http://github.com/blitz-research/
|
||||
|
||||
Include "Example_Shared.bb"
|
||||
ExampleInit()
|
||||
|
||||
; Our Type will hold one of every Element.
|
||||
Type EverythingType
|
||||
Field MyInt%
|
||||
Field MyFloat#
|
||||
Field MyString$
|
||||
Field MyObject.EverythingType
|
||||
; It is important to note that Blitz doesn't consider Arrays as pointers, but
|
||||
; as solid blocks in memory instead. This is why we can't make them dynamic,
|
||||
; and have to use Dim or Banks.
|
||||
Field MyIntArray%[5]
|
||||
Field MyFloatArray#[5]
|
||||
Field MyStringArray$[5]
|
||||
Field MyObjectArray.EverythingType[5]
|
||||
End Type
|
||||
|
||||
; And create a function that modifies only using pointers.
|
||||
Global fpMyPointerFunction% = 0
|
||||
Function MyPointerFunction(Pointer%)
|
||||
If fpMyPointerFunction = 0 Then
|
||||
fpMyPointerFunction = BP_GetFunctionPointer()
|
||||
Return
|
||||
EndIf
|
||||
|
||||
; Simple Memory modification
|
||||
PokeMemoryInt Pointer + 20, PeekMemoryInt(Pointer + 20) + 1
|
||||
PokeMemoryFloat Pointer + 24, PeekMemoryFloat(Pointer + 24) + 1
|
||||
|
||||
; Sick of reference counting? Do Circular References without incrementing that!
|
||||
PokeMemoryInt Pointer + 32, Pointer
|
||||
End Function
|
||||
MyPointerFunction(0)
|
||||
|
||||
Local Instance.EverythingType = New EverythingType
|
||||
|
||||
While Not KeyHit(1)
|
||||
ExampleUpdate()
|
||||
|
||||
MyPointerFunction(Int(Instance))
|
||||
|
||||
Text 0, 0, "\MyInt"
|
||||
Text 200, 0, Instance\MyInt
|
||||
Text 0,15, "\MyFloat"
|
||||
Text 200,15, Instance\MyFloat
|
||||
; Circular Reference
|
||||
Text 0,45, "\MyObject\MyInt"
|
||||
Text 200,45, Instance\MyObject\MyInt
|
||||
Text 0,60, "\MyObject\MyObject\MyInt"
|
||||
Text 200,60, Instance\MyObject\MyObject\MyInt
|
||||
|
||||
ExampleLoop()
|
||||
Wend
|
||||
End
|
||||
;~IDEal Editor Parameters:
|
||||
;~C#Blitz3D
|
||||
@@ -0,0 +1,315 @@
|
||||
; BlitzPointer - Adding Pointers to Blitz.
|
||||
; Copyright (C) 2015 Project Kube (Michael Fabian Dirks)
|
||||
;
|
||||
; This program is free software: you can redistribute it and/or modify
|
||||
; it under the terms of the GNU Lesser General Public License as
|
||||
; published by the Free Software Foundation, either version 3 of the
|
||||
; License, or (at your option) any later version.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU Lesser General Public License
|
||||
; along with this program. If not, see <http:;www.gnu.org/licenses/>.
|
||||
|
||||
; ---------------------------------------------------------------------------- ;
|
||||
; Example 6 - Callbacks
|
||||
; ---------------------------------------------------------------------------- ;
|
||||
; License: Creative Commons Attribution 2.0
|
||||
; Author: Michael Fabian Dirks<michael.dirks@realitybends.de>
|
||||
; Prerequisite: Example 5
|
||||
|
||||
; In my opinion, Callbacks are one of the best things that people have figured
|
||||
; out is useful. We can completely combine all our update logic into one single
|
||||
; function call without ever having to worry about how to handle a new object.
|
||||
; Well, unless you are a terrible planner anyways.
|
||||
|
||||
Include "Example_Shared.bb"
|
||||
ExampleInit()
|
||||
SeedRnd MilliSecs()
|
||||
|
||||
; We'll begin by creating a basic Type that holds our generic object. By itself
|
||||
; this generic object does nothing, but we define custom callbacks later on.
|
||||
; For optimization reasons (saves some memory) we can use a manually defined
|
||||
; index for our callbacks.
|
||||
|
||||
; Using an Index to store our Callbacks is more efficient that storing it for
|
||||
; each entry. By doing this we can also have multiple functions that use the
|
||||
; same structure (Update, PhysicsUpdate, Render, ...). It is wise to reserve
|
||||
; the first index to check for incorrectly created objects.
|
||||
Dim CallbackIndex(10)
|
||||
|
||||
; Here we define our Type. Since each object has an Index, we
|
||||
Type TGeneric
|
||||
; For optimization reasons and saving memory, we just store a callback index.
|
||||
Field Index
|
||||
|
||||
; We only need to store the pointer to our Type object, nothing else.
|
||||
Field Pointer
|
||||
End Type
|
||||
|
||||
Function TGenericUpdate()
|
||||
Local This.TGeneric
|
||||
For This = Each TGeneric
|
||||
If This\Pointer <> 0 Then
|
||||
If BP_CallFunctionII(CallbackIndex(This\Index), This\Pointer) Then
|
||||
Delete This
|
||||
EndIf
|
||||
EndIf
|
||||
Next
|
||||
End Function
|
||||
|
||||
; TGeneric will call a function pointer with the following footprint:
|
||||
; int FUNCTION(pointer)
|
||||
; We will need to implement this function footprint in every callback.
|
||||
|
||||
; Our first Type will hold Cubes that moves up and down.
|
||||
Type TCube
|
||||
; Our TCube is represented by an actual Cube in the world, so let's store it.
|
||||
Field Entity
|
||||
; This is the original position of the Cube. Y is dynamically modified in code.
|
||||
Field PosX#, PosY#, PosZ#
|
||||
; And finally, the time it was created.
|
||||
Field Time
|
||||
End Type
|
||||
; Assign an index to our new Type (starting at 1)
|
||||
Const CALLBACK_INDEX_TCUBE% = 1
|
||||
|
||||
Function TCubeCreate.TCube(X#, Y#, Z#)
|
||||
; Create our Object
|
||||
Local This.TCube = New TCube
|
||||
This\Entity = CreateCube(Example_SceneRoot)
|
||||
This\PosX = X
|
||||
This\PosY = Y
|
||||
This\PosZ = Z
|
||||
This\Time = MilliSecs()
|
||||
|
||||
; And now store it withing TGeneric
|
||||
Local TG.TGeneric = New TGeneric
|
||||
TG\Index = CALLBACK_INDEX_TCUBE
|
||||
; To get the pointer we need (and can store), we just use Int() on the object.
|
||||
TG\Pointer = Int(This)
|
||||
|
||||
; That's all we had to do.
|
||||
Return This
|
||||
End Function
|
||||
|
||||
Function TCubeCallback%(This.TCube)
|
||||
If CallbackIndex(CALLBACK_INDEX_TCUBE) = 0 Then
|
||||
CallbackIndex(CALLBACK_INDEX_TCUBE) = BP_GetFunctionPointer()
|
||||
Return
|
||||
EndIf
|
||||
; Safeguard against stupidity (it affect everyone).
|
||||
If This = Null Then Return True
|
||||
|
||||
Local TimeDiff = (MilliSecs() - This\Time)
|
||||
|
||||
Local YOffset# = Cos((Cos(This\PosX) * 180) + (Sin(This\PosZ) * 180) + (TimeDiff / 10.0)) * 5 + 5
|
||||
PositionEntity This\Entity, This\PosX, This\PosY + YOffset, This\PosZ
|
||||
EntityAlpha This\Entity, 1.0 - (TimeDiff / 5000.0)
|
||||
|
||||
; We will allow the object to exist for at most 5 seconds.
|
||||
If TimeDiff > 5000 Then
|
||||
TCubeDestroy(This)
|
||||
Return True
|
||||
EndIf
|
||||
Return False
|
||||
End Function
|
||||
|
||||
Function TCubeDestroy(This.TCube)
|
||||
; Safeguard against stupidity (it affect everyone).
|
||||
If This = Null Then Return
|
||||
|
||||
FreeEntity This\Entity
|
||||
Delete This
|
||||
End Function
|
||||
|
||||
; And call the function once to automagically register it as a callback.
|
||||
TCubeCallback(Null)
|
||||
|
||||
; Next up is our second Type. It will hold a simple sphere that grows over time.
|
||||
Type TSphere
|
||||
; Again, represented by an actual Sphere in the world.
|
||||
Field Entity
|
||||
; And the time it was created.
|
||||
Field Time
|
||||
End Type
|
||||
; And we will assign the second index to it.
|
||||
Const CALLBACK_INDEX_TSPHERE% = 2
|
||||
|
||||
Function TSphereCreate.TSphere(X#, Y#, Z#)
|
||||
; Initialize our TSphere instance.
|
||||
Local This.TSphere = New TSphere
|
||||
This\Entity = CreateSphere(32, Example_SceneRoot)
|
||||
PositionEntity This\Entity, X, Y, Z
|
||||
This\Time = MilliSecs()
|
||||
|
||||
; And now store it withing TGeneric
|
||||
Local TG.TGeneric = New TGeneric
|
||||
TG\Index = CALLBACK_INDEX_TSPHERE
|
||||
TG\Pointer = Int(This)
|
||||
|
||||
Return This
|
||||
End Function
|
||||
|
||||
Function TSphereUpdate%(This.TSphere)
|
||||
If CallbackIndex(CALLBACK_INDEX_TSPHERE) = 0 Then
|
||||
CallbackIndex(CALLBACK_INDEX_TSPHERE) = BP_GetFunctionPointer()
|
||||
Return
|
||||
EndIf
|
||||
; Safeguard against stupidity (it affect everyone).
|
||||
If This = Null Then Return True
|
||||
|
||||
Local TimeDiff = (MilliSecs() - This\Time)
|
||||
Local TimePrc# = TimeDiff / 2500.0
|
||||
|
||||
Local Stp#, StpSize#
|
||||
Local R#, G#, B#, A#, Scale#
|
||||
;Step
|
||||
StpSize# = 0.05:Stp# = 1.0 / (1.0 - StpSize)
|
||||
R = Interp(1, 1, TimePrc * Stp)
|
||||
G = Interp(1, 1, TimePrc * Stp)
|
||||
B = Interp(1, 0, TimePrc * Stp)
|
||||
;Step
|
||||
StpSize# = 0.20:Stp# = 1.0 / (1.0 - StpSize)
|
||||
R = Interp(R, 1, (TimePrc - 0.05) * Stp)
|
||||
G = Interp(G, 0.75, (TimePrc - 0.05) * Stp)
|
||||
B = Interp(B, 0, (TimePrc - 0.05) * Stp)
|
||||
;Step
|
||||
StpSize# = 0.25:Stp# = 1.0 / (1.0 - StpSize)
|
||||
R = Interp(R, 1, (TimePrc - 0.25) * Stp)
|
||||
G = Interp(G, 0, (TimePrc - 0.25) * Stp)
|
||||
B = Interp(B, 0, (TimePrc - 0.25) * Stp)
|
||||
;Step
|
||||
StpSize# = 0.50:Stp# = 1.0 / (1.0 - StpSize)
|
||||
R = Interp(R, 0, (TimePrc - 0.50) * Stp)
|
||||
G = Interp(G, 0, (TimePrc - 0.50) * Stp)
|
||||
B = Interp(B, 0, (TimePrc - 0.50) * Stp)
|
||||
|
||||
;AlphaStop 1 at (0.8 of 1.0)
|
||||
A = Interp(1, 0, (TimePrc - 0.8) * 5)
|
||||
|
||||
Scale = Interp(1, 20, Sin(TimePrc * 90))
|
||||
ScaleEntity This\Entity, Scale,Scale,Scale
|
||||
EntityColor This\Entity, R * 255, G * 255, B * 255
|
||||
EntityAlpha This\Entity, A
|
||||
|
||||
; We will allow the object to exist for at most 2.5 seconds.
|
||||
If TimeDiff > 2500 Then
|
||||
TSphereDestroy(This)
|
||||
Return True
|
||||
EndIf
|
||||
Return False
|
||||
End Function
|
||||
TSphereUpdate(Null)
|
||||
|
||||
Function TSphereDestroy(This.TSphere)
|
||||
; Safeguard against stupidity (it affect everyone).
|
||||
If This = Null Then Return
|
||||
|
||||
FreeEntity This\Entity
|
||||
Delete This
|
||||
End Function
|
||||
|
||||
; And finally, a terrain that we can pick a spawning position from.
|
||||
Local Terrain = CreateTerrain(256, Example_SceneRoot)
|
||||
ScaleEntity Terrain, 1 / 256.0, 64, 1 / 256.0
|
||||
MoveEntity Terrain, -100, 0, -100
|
||||
ScaleEntity Terrain, 1 / 256.0 * 201, 64, 1 / 256.0 * 201
|
||||
EntityColor Terrain, 25, 92, 25
|
||||
TerrainShading Terrain, True
|
||||
TerrainDetail Terrain, 32767, False
|
||||
EntityPickMode Terrain, 2, True
|
||||
|
||||
RandomTerrain(Terrain, 256, 8, 8)
|
||||
|
||||
MoveEntity Example_Camera, 0, 0, -125
|
||||
;HideEntity Example_Floor
|
||||
|
||||
While Not KeyHit(1)
|
||||
TGenericUpdate()
|
||||
|
||||
; Space to randomize Terrain
|
||||
If KeyHit(57) Then
|
||||
RandomTerrain(Terrain, 256, Rand(1,8), Rand(1,8))
|
||||
EndIf
|
||||
|
||||
Local ZDelta = MouseZSpeed()
|
||||
If KeyHit(2) Or ZDelta > 0 Then
|
||||
CameraPick(Example_Camera, MouseX(), MouseY())
|
||||
TCubeCreate(PickedX(), PickedY(), PickedZ())
|
||||
EndIf
|
||||
|
||||
If KeyHit(3) Or ZDelta < 0 Then
|
||||
CameraPick(Example_Camera, MouseX(), MouseY())
|
||||
TSphereCreate(PickedX(), PickedY(), PickedZ())
|
||||
EndIf
|
||||
|
||||
ExampleUpdate()
|
||||
ExampleLoop()
|
||||
UpdateWorld()
|
||||
Wend
|
||||
|
||||
Function RandomTerrain(Terrain, GridSize, CellsX = 1, CellsZ = 1)
|
||||
Local CellW, CellH, CellX, CellZ, TerX, TerZ, CellPrcX#, CellPrcZ#
|
||||
Local HTL#, HTR#, HBL#, HBR#, HCC#
|
||||
|
||||
CellW = Floor(GridSize / Float(CellsX))
|
||||
CellH = Floor(GridSize / Float(CellsZ))
|
||||
|
||||
Local RowSize = CellsZ + 1
|
||||
Local TempBankSize = (CellsX + 1) * RowSize * 4
|
||||
Local TempBank = CreateBank(TempBankSize)
|
||||
For CellX = 0 To CellsX
|
||||
For CellZ = 0 To CellsZ
|
||||
PokeFloat TempBank, 4 * (CellX * RowSize + CellZ), Rnd(0, 1)
|
||||
Next
|
||||
Next
|
||||
|
||||
Local OCellX, OCellZ:OCellX = -1: OCellZ = -1
|
||||
For TerX = 1 To (GridSize - 1)
|
||||
CellX = Floor(TerX / Float(CellW))
|
||||
CellPrcX = (TerX Mod CellW) / Float(CellW - 1)
|
||||
For TerZ = 1 To (GridSize - 1)
|
||||
CellZ = Floor(TerZ / Float(CellH))
|
||||
CellPrcZ = (TerZ Mod CellH) / Float(CellH - 1)
|
||||
;DebugLog CellPrcZ
|
||||
|
||||
If CellX <> OCellX Or CellZ <> OCellZ Then
|
||||
HTL = PeekFloat(TempBank, 4 * (((CellX + 0) * RowSize + (CellZ + 0))))
|
||||
HTR = PeekFloat(TempBank, 4 * (((CellX + 1) * RowSize + (CellZ + 0))))
|
||||
HBL = PeekFloat(TempBank, 4 * (((CellX + 0) * RowSize + (CellZ + 1))))
|
||||
HBR = PeekFloat(TempBank, 4 * (((CellX + 1) * RowSize + (CellZ + 1))))
|
||||
OCellX = CellX:OCellZ = CellZ
|
||||
EndIf
|
||||
|
||||
Local PrcX#, PrcZ#
|
||||
; Normally, you'd use a bezier curve for this.
|
||||
PrcX = (Sin(-90 + CellPrcX*180) * 0.5 + 0.5)
|
||||
PrcZ = (Sin(-90 + CellPrcZ*180) * 0.5 + 0.5)
|
||||
Local Height# = Interp(Interp(HTL, HTR, PrcX), Interp(HBL, HBR, PrcX), PrcZ)
|
||||
|
||||
ModifyTerrain Terrain, TerX, TerZ, Height
|
||||
Next
|
||||
Next
|
||||
FreeBank TempBank
|
||||
End Function
|
||||
|
||||
Function Min#(A#, B#)
|
||||
If B < A Then Return B
|
||||
Return A
|
||||
End Function
|
||||
|
||||
Function Max#(A#, B#)
|
||||
If B > A Then Return B
|
||||
Return A
|
||||
End Function
|
||||
|
||||
Function Interp#(L#, R#, Lerp#)
|
||||
Lerp = Min(Max(Lerp, 0.0), 1.0)
|
||||
Return L * (1.0 - Lerp) + R * Lerp
|
||||
End Function
|
||||
;~IDEal Editor Parameters:
|
||||
;~C#Blitz3D
|
||||
@@ -0,0 +1,83 @@
|
||||
; BlitzPointer - Adding Pointers to Blitz.
|
||||
; Copyright (C) 2015 Project Kube (Michael Fabian Dirks)
|
||||
;
|
||||
; This program is free software: you can redistribute it and/or modify
|
||||
; it under the terms of the GNU Lesser General Public License as
|
||||
; published by the Free Software Foundation, either version 3 of the
|
||||
; License, or (at your option) any later version.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU Lesser General Public License
|
||||
; along with this program. If not, see <http:;www.gnu.org/licenses/>.
|
||||
|
||||
Global Example_Timer
|
||||
; Camera
|
||||
Global Example_Camera_YawPivot
|
||||
Global Example_Camera_PitchPivot
|
||||
Global Example_Camera
|
||||
; Scene
|
||||
Global Example_SceneRoot
|
||||
Global Example_SceneLight
|
||||
Global Example_Floor
|
||||
Global Example_Block
|
||||
|
||||
Function ExampleInit()
|
||||
Example_Timer = CreateTimer(60)
|
||||
|
||||
Graphics3D 1024, 768, 32, 2
|
||||
SetBuffer BackBuffer()
|
||||
|
||||
Example_Camera_YawPivot = CreatePivot()
|
||||
Example_Camera_PitchPivot = CreatePivot(Example_Camera_YawPivot)
|
||||
Example_Camera = CreateCamera(Example_Camera_PitchPivot)
|
||||
MoveEntity Example_Camera, 0, 0, -20
|
||||
TurnEntity Example_Camera_PitchPivot, 30, 0, 0
|
||||
|
||||
Example_SceneRoot = CreatePivot()
|
||||
|
||||
AmbientLight 51, 51, 51
|
||||
Example_SceneLight = CreateLight(1, Example_SceneRoot)
|
||||
RotateEntity Example_SceneLight, 70, 30, 0
|
||||
|
||||
Example_Floor = CreateCube(Example_SceneRoot)
|
||||
EntityColor Example_Floor, 153, 255, 153
|
||||
EntityShininess Example_Floor, 1.0
|
||||
ScaleEntity Example_Floor, 100, 0.001, 100
|
||||
|
||||
;Example_Block = CreateCube(Example_SceneRoot)
|
||||
;MoveEntity Example_Block, 0, 1, 0
|
||||
End Function
|
||||
|
||||
Function ExampleUpdate()
|
||||
Local MX#, MY#
|
||||
|
||||
MX = (MouseX() - 512) / 512.0
|
||||
MY = (MouseY() - 384) / 384.0
|
||||
|
||||
If MouseHit(1) Then
|
||||
MoveMouse 512, 384
|
||||
ElseIf MouseDown(1) Then
|
||||
TurnEntity Example_Camera_YawPivot, 0, -MX, 0
|
||||
TurnEntity Example_Camera_PitchPivot, MY, 0, 0
|
||||
;MoveMouse 512, 384
|
||||
EndIf
|
||||
|
||||
If MouseHit(2) Then
|
||||
MoveMouse 512, 384
|
||||
ElseIf MouseDown(2) Then
|
||||
MoveEntity Example_Camera, 0, 0, MY
|
||||
;MoveMouse 512, 384
|
||||
EndIf
|
||||
|
||||
RenderWorld
|
||||
End Function
|
||||
|
||||
Function ExampleLoop()
|
||||
Flip 0:Cls:WaitTimer(Example_Timer)
|
||||
End Function
|
||||
;~IDEal Editor Parameters:
|
||||
;~C#Blitz3D
|
||||
Reference in New Issue
Block a user