Jump to content

Paul Thomas

Members
  • Posts

    339
  • Joined

  • Last visited

Posts posted by Paul Thomas

  1. 13. Works on onboard intel GPU chip

     

    Hopefully you know you can't have all of those features working with this part of your list because that isn't possible. Otherwise, besides I think APEX, you're describing CE3. If you plan on all of these GPU intensive features then I wouldn't even worry over Intel. It honestly sounds like you're only looking for what you've read about or you don't have your project completely flushed out and ready to be built.

     

    You need to base your engine around your project/game, not the other way around, and then shop for the right engine. The other part of the decision, besides what's based on your project and platform, is if you can afford royalty as that will drastically change which engines to decide on. It also, obviously, depends on your experience level and skills on everything as a whole. If you're trying to learn then I would definitely say LE is worth the money if you have it. If you're looking for a one shot deal into commercial, without any experience or skills, I'd say drop the dreams for the now and start with a mobile game, work your way up, and see where you stand from there.

     

    Good luck.

  2. All loads good here, NA.

     

    My only suggestion is the twitter background color (sticks out like a sore thumb compared to the overal color scheme) and the type of blue font you use in the body I would just make it white. Basically what gamecreator said. The colors clash with the overall theme and art.

     

    Art looks great, great job on that.

  3. C++ version to send a message to BMax window (yes, it's specific, any other way doesn't work correctly that I've noticed):

     

    HWND pHandle = FindWindow(NULL, _T("WINDOW TITLE"));
    
    if(pHandle != NULL && GetLastError() != ERROR_SUCCESS)
    {
     std::string msgString = "THIS IS A TEST";
    
     COPYDATASTRUCT dataStruct;
     dataStruct.dwData = 3;  // this just tells my app that this is coming from C++ DLL - use any number
     dataStruct.cpData = (msgString.length() + 1);
     dataStruct.lpData = (PVOID)msgString.c_str();
    
     LRESULT msgSent = SendMessage(pHandle, WM_COPYDATA, (WPARAM)pHandle, (LPARAM)(LPVOID)&dataStruct);
    }
    

     

    I still cannot figure out why BMax cannot read from the named pipe (different subject, just using this spot for quick thoughts). Using pure C++ I have no problems, BMax can only send, but not receive. I'm guessing it's something wrong I'm doing in BMax but it's hard to tell.

  4. I just now got this working and I haven't made it all organized yet, I'm going to do that when I add it to my actual application, instead of using this testing application. One portion turned out to be a problem. When trying to get the window handle from the process ID it actually is a list of the window and basically any/all gadgets that can receive messages (active panels for example). I don't know for fact that this is true but that's what it seems like to me, otherwise I don't see how all of these returned results from "GetWindowThreadProcessId" are all from the same process ID.

     

    Here is the function get the results from a process ID, one of which will be the window, and this has to be filtered in some way (send a message, check the title, something along those lines; I haven't done this filter yet):

     

    ' get the list of threads/windows matching the passed in process id '
    Function GetProcessWindow:int[](id:int)
     Local hWnd:int = GetTopWindow(0)
     Local hWnds:int[]
    
    While(hWnd)
      Local pId:int
      Local dThreadId:int = GetWindowThreadProcessId(hWnd, Varptr pId)
    
    	If pId = id
    	  hWnds = hWnds[..hWnds.Length+1]
    	  hWnds[hWnds.Length-1] = hWnd
    	EndIf
    
      hWnd = _GetNextWindow(hWnd, GW_HWNDNEXT)
    Wend
    
     Return hWnds
    EndFunction
    

     

    Now, you can use this list and send the message to all of them, which I did to be quick about it, and it seems safe because the message will just fail to send if it's not a correct window. That seems odd, so a filtering process should be done, but I haven't done that yet. Either way you will still be sending a message of some kind to all of the returned results before having the actual window handle.

     

    Anyway, the following is how to send the message (which would be a separate application at the time) and receive it (which would be the already running instance of the application).

     

    Sending:

    Global ChangeWindowMessageFilter:Int(message:Int, dwFlag:Int) = GetProcAddress(LoadLibraryA("user32.dll"), "ChangeWindowMessageFilter")
    
    Local MsgStr:String = "THIS IS A TEST"
    Local MsgData:int[3]
    MsgData[0] = 1
    MsgData[1] = Len(MsgStr) + 1
    MsgData[2] = Int(MsgStr.ToCString())
    
    ChangeWindowMessageFilter(WM_COPYDATA, 1)
    SendMessageW(pHandle, WM_COPYDATA, 0, Int Byte Ptr MsgData)
    

     

    Receiving:

    Local MsgData:int[3]
    MemCopy(MsgData, Byte Ptr lp, 12)
    
    ' MsgData[0] - 1 '
    ' MsgData[1] - Size '
    ' MsgData[2] - String '
    
    Notify(String.FromCString(Byte Ptr MsgData[2]))
    

     

    And there you have it. It will notify "THIS IS A TEST" correctly. You can use "MsgData[0]" as a form of message identification so you can decide what to do with the string you've received.

     

     

     

    For receiving, it's best to edit "win32maxguiex.bmx" and explains the "lp" variable. Line 372, you would do something like:

    ' Select msg '
     Case WM_COPYDATA
    local msgData:int[3]
    MemCopy(msgData, Byte Ptr lp, 12)
    
    PostGuiEvent(EVENT_DATARECEIVED, Null, 0, 0, 0, 0, String.FromCString(Byte Ptr msgData[2]))
    

     

    Add the "EVENT_DATARECEIVED" to "brl.mod/event.bmx", around line 193:

    Const EVENT_DATARECEIVED=$50000
    

     

    And around line 234:

    TEvent.RegisterId EVENT_DATARECEIVED,"DataReceived"
    

     

    Rebuild the two modules, and now you can use it like:

    repeat
     waitevent()
    
     select eventid()
    
    case EVENT_DATARECEIVED
      notify(eventextra().tostring())
    

     

    That should be it.

     

     

    Thanks goes out to "col" from the BlitzMax forums for his help in figuring out the sending/receiving of the message.

  5. Had this working but never tested actually getting the message, I only confirmed it worked with a notification, and so I spent all day trying to actually get the message. Going to give this more of a shot but if I still can't get it working strictly in BMax I'm probably going to take a shortcut and provide a helper function in C.

  6. I would imagine anyone who uses LE editor for a long period of time would have seen this happen and probably would have reported it. I also never had seen Flexman mention this before either. So, either no one has used the editor for a long period of time, or Flexman/NA never played their own games for a long period of time, or it's something you're doing.

     

    I will come back and post here if I see it happen.

  7. lol, technically yeah, I could make my own task manager.

     

    However, my purpose is to deny multiple instances of my application, and eventually send messages (SendMessageW) to the application - which I'm working on now. My attempt is to deny a second application execution and send the application arguments to the application already running (this way double clicking a file that my application is registered to will open up in the application already running).

     

    Forgot about the tags.

     

    And fixed.

  8. xwinuser.c

    #include "xwinuser.h"
    
    HWND _GetNextWindow(HWND hWnd, UINT wCmd)
    {
      return GetNextWindow(hWnd, wCmd);
    }
    

     

    xwinuser.h

    #include <Windows.h>
    #include <Winuser.h>
    
    #ifdef __cplusplus
    extern "C"{
    #endif
    
    extern HWND _GetNextWindow(HWND hWnd, UINT wCmd);
    
    #ifdef __cplusplus
    }
    #endif
    

     

    BMAX

    Import "xwinuser.c"
    
    Const GW_HWNDNEXT:int = 2
    Const GW_HWNDPREV:int = 3
    
    Extern "Win32"
       Function _GetNextWindow:Int(hWnd:Int, wCmd:Int) = "_GetNextWindow"
    EndExtern
    
    

     

    Not sure if this would be called "proper" but it works.

  9. I started working on this today, got it working, and figured I'd share. I still have more work to do but this is a good start. Could use cleaning up but that's for later.

     

    SuperStrict
    
    Import "-lpsapi"
    
    Const PROCESS_QUERY_INFORMATION:Int = $0400
    Const PROCESS_VM_READ:Int = $0010
    Const PROCESS_VM_WRITE:Int = $0020
    
    Extern "Win32"
    Function GetLastError:Int()
    Function OpenProcess:Int(dwDesiredAccess:Int, bInheritHandle:Int, dwProcessId:Int)
    Function EnumProcesses(pProcessIds:Byte Ptr, cb:Int, pBytesReturned:Int Ptr)="EnumProcesses@12"
    Function EnumProcessModules(hProcess:Int, lphModule:Byte Ptr, cb:Int, lpcbNeeded:Int Ptr)
    Function GetModuleBaseName(hProcess:Int, hModule:Int, lpBaseName:Byte Ptr, nSize:Int) = "GetModuleBaseNameA@16"
    Function TerminateProcess(hProcess:Int, uExitCode:Int)
    Function CloseHandle(hObject:Int)
    Function GetModuleFileName(hModule:Int, lpFileName:Byte Ptr, nSize:Int)
    Function GetModuleFileNameExA(hProcess:Int, hModule:Int, lpFilename:Byte Ptr, nSize:Int)
    Function GetProcessImageFileNameA(hProcess:Int, lpImageFileName:Byte Ptr, nSize:Int)
    EndExtern
    
    ' enumerate all processes '
    Function EnumerateProcesses:Int[]()
    Local pProcessIds:Byte Ptr
    Local cb:Int = 1024
    Local bBytesReturned:Int
    Local processes:Int[]
    
    pProcessIds = MemAlloc(cb)
    	If Not EnumProcesses(pProcessIds , cb, Varptr bBytesReturned)
    		MemFree(pProcessIds )
    		Return Null
    	EndIf
    processes = New Int[bBytesReturned / 4]
    MemCopy(Varptr processes[0], pProcessIds, bBytesReturned)
    MemFree(pProcessIds)
    
    Return processes
    EndFunction
    
    ' get process name from process id '
    Function GetProcessName:String(id:Int)
    Local hProcess:Int
    Local hModule:Int = 0
    Local lpBaseName:Byte Ptr[1024]
    Local nSize:Int = 1024
    Local processName:String = ""
    
    hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, 0, id)
    	If hProcess = 0 Return ""
    
    GetModuleBaseName(hProcess, hModule, Varptr lpBaseName[0], nSize)
    
    processName = String.FromCString(lpBaseName)
    
    	If processName = "?" Or processName = Null
    		GetProcessImageFileNameA(hProcess, Varptr lpBaseName[0], nSize)
    		processName = StripDir(String.FromCString(lpBaseName))
    	EndIf
    
    CloseHandle(hProcess)
    
    Return processName
    EndFunction
    
    ' EXAMPLE USEAGE '
    
    Local pList:Int[] = EnumerateProcesses()
    
      If pList.length > 0
    
    	 For Local i:Int = 0 To pList.length - 1
    
    		   If pList[i] <> 0
    
    			  Local pname:String = GetProcessName(pList[i])
    
    				 If pname <> "" Notify(pname)
    
    		   EndIf
    
    	 Next
    
      EndIf
    
    

  10. You're using static camera positions, you could take advantage of that and alter the level design. For example, at around 0:37, you could be using a billboard in the distance instead of sculpting hills. Would most likely have a better visual result as well, depending on how well the art could be done for it, but overall it would let you decrease the size of the terrain. I'm not sure how much performance you'd gain from doing that but it's better than nothing.

     

    How are you handling the animals once they are out of view? You can again take advantage of static camera positions and never actually delete the animal, but instead hide and move them to another location just to run into view again. Animals that run out of view without dying can be recycled in the same way (be sure to reset their health points too on all of these animals being recycled).

     

    Other than sneaky art trickery on the level design you may need to investigate the animal meshes, see if they could be optimized, not sure if you purchased these animals or made them yourself.

     

    That's about all I can think of for the moment, maybe someone else will have more tips.

  11. Texture size would be the same, the only real difference using a mesh and painting the mesh would be less textures used, since it would all be painted on a single texture. I wouldn't go below 4096 unless you plan on a lot of vegetation because any lower resolution looks kind of bad. I would use 4096 on parts of the terrain that would have no, or very little, vegetation, and 2048 (maybe even 1024) on high vegetation density areas.

     

    The only downside to using mesh is ease of editing compared but I guess that really depends on your modeling/sculpting skills. You'd also have to make sure each section of mesh aligns with the next within your modeling program. Having your level already conceptualized before modeling would reduce the amount of edits you would have to do, because I can imagine a situation where you decided to make clearing for a building right at a location where four meshes combine to make the area. Not only would you be editing the four meshes but also repainting those meshes. You should also definitely have LOD's for your terrain meshes but you don't have to bother if you don't plan on open fields/areas.

     

    The overall level design concept should help define how the level should be designed. I predict multiple meshes instead of one large mesh so that the engine can cull sections correctly. Really all depends on the overall level design, what you need, and so on.

    • Upvote 1
  12. The problem with the collision is what Marley's Ghost has been talking about: http://www.leadwerks.com/werkspace/topic/4482-linepicks-and-veg-layers/

     

    Vegetation layers are blocking traces even though their collision is set to 0. Either Josh fixes it or you do away with using vegetation layers. Unless you meant the random animals running through some of the tree's.

     

    Everything looks good. Some of the animal running animations look too slow. The dust particles could be smaller for their running and add in particles when they are collapsing to the ground (about as large, or larger, than their current running particles). Need some bullet hit impacts with the environment and maybe the animals (you said arcade, so maybe no the animals/blood).

     

    That's all I got, good work.

  13. Also, I used something similar to what you did Josh for a slightly different purpose. I also used a thread so my UI doesn't freeze up during the process:

     

    field thread:tthread
    
    method beginprocess()
     thread = createthread(runprocess, null)
    endmethod
    
    function runprocess:object(data:object)
     local line:string = ""
     local lines:string = ""
     local process:tprocess = createprocess(PROCESSLOCATION, 1)
    
       while process.status()
      line = process.pipe.readline().trim()
        if line <> "" lines :+ line + "~n";
       wend
    
     ' process lines '
    
     process.terminate()
    endfunction
    

     

    Technically don't need to terminate the process at the end since it'll terminate once the thread is finished but it doesn't hurt. Every time I'm using processes I'm parsing it line by line so I edited the above to add all the lines.

     

    Meh, just felt like sharing code.

  14. Almost finished, now I just need to figure out why I get a ERROR_NOACCESS (998) when trying to get BMax to read a response from the pipe after the DLL had received a message and sent one back. Then I have to make sure neither are causing any memory leaks or hogging CPU or anything like that.

     

    It's been a long and strange battle learning C++. If I was learning properly I would be okay but I was kind of forced into this and trying to be as quick as possible. The overall objective of this whole thing is communication between two processes. The DLL is loaded by another application (I could edit the source of that application, rebuilding it to use a named pipe instead of the DLL, but that's like editing Mount Rushmore to put an eyelash or two on George Washington) and executes specific functions for specific actions/responses by the application. I needed to build a communication layer between the DLL and my BlitzMax application. Hopefully this is the right answer.

     

    For my next personal challenge I was thinking of making a C++ DLL that can give me handles/pointers to processes but at the moment I don't even know where to begin that using C++. My main purpose for that is for two reasons; 1) To deny an application from opening twice (Josh, you pointed me to a interprocesses module but it won't compile correctly; do you have a compiled version you could send?), 2) to set window focus between one process and another.

     

    Thanks to everyone who helped me through this whole ordeal, greatly appreciated.

×
×
  • Create New...