-
Posts
339 -
Joined
-
Last visited
Content Type
Blogs
Forums
Store
Gallery
Videos
Posts posted by Paul Thomas
-
-
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.
-
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.
-
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.
-
LMAO, very nice work MG.
-
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.
-
Very nice work, Ken. You display some awesome skills.
-
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.
-
Nice find Roland, thanks for sharing.
-
Got this working but now I need to clean everything up.
-
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.
-
I've never had that happen.
-
Good catch.
-
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.
-
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.
-
Wow, "GetTopWindow" is in User32.dll but "GetNextWindow" is only available in Winuser.h? That is so lame.
-
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
-
-
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.
-
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.
- 1
-
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.
-
I've never had that problem. Image -> Image Size...
-
Can't you just throw them into Photoshop, use recorded actions on the entire texture folder, the recorded action simply / 2 or / 4 scale and save?
-
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.
-
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.
I found Leadweks in TGC website
in General Discussion
Posted
Sorry Josh, was that a reply to me? If so, which company are you talking about?