Jump to content

Willicious

Members
  • Content Count

    93
  • Joined

  • Last visited

Everything posted by Willicious

  1. Willicious

    Change "FadeOut" code to "FadeIn" code

    @Anders Melander Ah, maybe there's been a misunderstanding. The idea is not to fade the current image to black, and then fade the same image back in. The idea is to fade the current image to black, and then fade the next image in. In fact, the way that the FadeOut; is written, it's always applied to any image which happens to be onscreen, at the point when that screen is closed. It doesn't need to know what the image is or what its exact colour values are. What's needed is a similarly-written FadeIn; procedure which can be applied to any screen.image, at the point when that screen is opened. Maybe it can be done by simply drawing a black canvas over the screen.image, and then gradually reducing the opacity until it's revealed (i.e. rather than having to get the actual colour values for each image)...?
  2. Willicious

    Change "FadeOut" code to "FadeIn" code

    I see what you mean, but I'm trying to fade from black to... some unknown colour (unknown in the sense that the bitmap contains many different colours). So, do I have to set those colour values first, and then call them something like "aValue"? If so, how do you do that for many different colours at once? Your example works for fading to black (and for modulating between known values).
  3. Willicious

    Change "FadeOut" code to "FadeIn" code

    Yeah, this seems useful. This is using FOpacity... would I need to draw a large black bitmap over the main one and then reduce the opacity of that bitmap to gradually reveal the one underneath?? I'm not sure how this works. Right, and I'm guessing that the "Value" needs to be explicitly stated? The bitmap has many different colour values, though. I need a way of saying "for each pixel, get the colour, and set this to some value. Now go from 0 to that value." It's not always going to be "1", so I'm not sure how to make use of your example...?
  4. Willicious

    Assign KeyDown function to btnClick

    Brilliant, thank you @programmerdelphi2k! This one worked: procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin if Key = vk_return { and other verifications... } then Button1.Click; end; And now, I know how to virtually click buttons, which is incredibly helpful 🙂👍
  5. Willicious

    RAD Studio Breakpoints not working

    Yes, fair enough. If others can benefit from this post, then great 👍 Deleting the .dcu files didn't help, and this was indeed the info I was getting from various sources. So, I tried just applying breakpoints to a bunch of random lines to see if it was something to do with the lines I was choosing to add breakpoints to, and it turns out that was the problem. I didn't realise that breakpoints were so selective. Ideally, if the user has chosen a line incorrectly (say, a "begin" line), the IDE would just intelligently choose the next available line that can be a breakpoint (or something) rather than just fail without explanation.
  6. Willicious

    RAD Studio Breakpoints not working

    OK, figured it out. It seems that certain lines don't actually allow breakpoints. MODS: Happy for this topic to be deleted.
  7. Hi all, The app I'm working on has a tree view which displays relevant info when an item in that tree is clicked with the mouse. It's also possible to scroll through the treeview list items using the arrow keys (which is obviously quicker than point-clicking every item to get the displayed info), however the info is not displayed when using the arrow keys. It's necessary to actually click an item to get it to display the info. Here's the relevant procedure: procedure TFLevelSelect.tvLevelSelectClick(Sender: TObject); begin SetInfo; end; As you can see, SetInfo is only called when the tree view is actually clicked. Do I need to add procedures for VK_DOWN and VK_UP which call this function, or can the hotkeys be added in here somewhere? Many thanks, Will
  8. Yes, thank you! The following code worked (i.e. setting an OnChange event for the treeview) 🙂 procedure TFLevelSelect.tvLevelSelectChange(Sender: TObject); begin SetInfo; end;
  9. Hi all, I'm attempting to hue shift a pre-loaded font graphic at a certain point on the screen where it appears as scroller text. I'm pretty sure I've entered everything correctly, but all I'm getting is completely blank text instead of hue-shifted text: procedure TGameMenuScreen.PrepareNextReelText; const HUE_SHIFT = 0.250; var i, realI: Integer; S: String; SizeRect: TRect; ScrollerText: TBitmap32; HueShift: TColorDiff; x, y: Integer; begin FillChar(HueShift, SizeOf(TColorDiff), 0); HueShift.HShift := HUE_SHIFT; ScrollerText := TBitmap32.Create; for i := 1 to fScrollerTextList.Count do begin if i = fScrollerTextList.Count then begin fDisableScroller := true; Exit; end; if fReelForceDirection < 0 then begin realI := (fReelTextIndex - i); if realI < 0 then realI := realI + fScrollerTextList.Count; end else realI := (fReelTextIndex + i) mod fScrollerTextList.Count; if Trim(fScrollerTextList[realI]) <> '' then begin S := Trim(fScrollerTextList[realI]); fReelTextIndex := realI; Break; end; end; try SizeRect := MenuFont.GetTextSize(S); ScrollerText.SetSize(SizeRect.Width, SizeRect.Height + 4); ScrollerText.Clear(0); MenuFont.DrawText(ScrollerText, S, 0, 4); for y := 0 to ScrollerText.Height-1 do for x := 0 to ScrollerText.Width-1 do begin ScrollerText[x, y] := ApplyColorShift(ScrollerText[x, y], HueShift); end; ScrollerText.DrawMode := dmBlend; finally ScrollerText.Free; end; if (fReelForceDirection < 0) then fReelTextPos := -ScrollerText.Width else fReelTextPos := LayoutInfo.ScrollerWidth; fLastReelUpdateTickCount := GetTickCount64; fSwitchedTextSinceForce := true; end; Any ideas what I'm either a) doing wrong or b) not doing at all? Thanks in advance!
  10. Willicious

    Applying hue change to font graphic on the fly

    OK... here's a perfect example of what beginners to programming are up against. "Classes" are something important, that much I can gather. But, I don't know what a "class" is or why it's important, so I look it up and here's what's presented: This raises far more questions than it answers. Now I need to know what "fields, methods and properties" are. I also need to know why you would have different instances of a class, and remember that these are referred to as "objects." I also need to remember that, as well as being called "fields, methods and properties", these things - whatever they are - may also be referred to as "components or members". And, there's 391 pages of this, with no index! So, as a beginner, I'm bound to think "maybe some of this stuff doesn't actually matter, and is just jargon. I'll just start changing things in the project and see what happens. If I need to 'know' something, I can just pick it up later, when it matters." So yes, I might occasionally not be aware that I'm incorrectly using a particular element of the language. But, I'm at a loss as to how else I could possibly learn everything. As someone should probably have once said, if they haven't already: "Si quieres aprender a hablar Español, ve a España!!"
  11. Willicious

    Applying hue change to font graphic on the fly

    The problem here is not that I don't understand Delphi, as such. It's more that I'm working on a very old program which has had several developers in the past, and whose codebase is therefore that bit more impenetrable to a beginner. As it happens, one of the previous devs was able to point me in the right direction with this. Basically, the Create; and Free; parts needed to be removed, since this is handled elsewhere. It only took a few small tweaks to what I'd done to put it right. Unfortunately, contact with the previous devs is limited at best, and I do want to try to solve some of this stuff without always going to them for help. To be quite honest, I didn't know that Result is only available in a function, but I do now, so thanks for pointing this out. I do take your point that something simple regarding structure is something I could perhaps learn better by swotting up a bit first, and I do plan on boosting my theoretical knowledge at some point, but this is likely to cost money (I'd prefer structured lessons with specific goals than just aimlessly reading books and/or worse, PDFs on a screen), so I'd prefer to wait until I can justify the expense a bit more. Since I'm currently working on a hobby project and getting a feel for programming in general, it doesn't seem worth shelling out just yet. With that said, I've watched several introductory videos on Delphi and other coding languages, and I find that I instantly forget most of what is said in these videos because I'm not actually using any of it. I just remember that something vague was said about classes, functions, something about semicolons and brackets, and yeah I can print "Hello World" to the screen, but what good is that when you're working on a game or website or complex desktop application? Don't get me wrong, I'm a former music teacher and I do understand the importance of theory in developing your skills, but my own personal preference is to have a go first, and then track back and see what I'm doing wrong if it doesn't work. I learn way more this way than by attempting to find that one video, article, chapter in a book, or - god forbid - Stack Overflow post that may or may not provide me with the knowledge I need to progress. Apologies for the rant here, I'm just finding learning programming very frustrating tbh. --- EDIT: I have downloaded the Delphi Language Guide. I'm taking a look at it 👍
  12. Willicious

    Applying hue change to font graphic on the fly

    function ApplyColorShift(aBase: TColor32; aDiff: TColorDiff): TColor32; var H, S, V: Single; begin RGBToHSV(aBase, H, S, V); H := H + aDiff.HShift; S := S + aDiff.SShift; V := V + aDiff.VShift; while H >= 1 do H := H - 1; while H < 0 do H := H + 1; S := Max(0, Min(S, 1)); V := Max(0, Min(V, 1)); Result := (HSVToRGB(H, S, V) and $FFFFFF) or (aBase and $FF000000); Result := TColor32(Integer(Result) + (aDiff.RAdj * $10000) + (aDiff.GAdj * $100) + (aDiff.BAdj)); // The typecasts avoid compiler warnings. end;
  13. Willicious

    Applying hue change to font graphic on the fly

    Tag added, apologies for the oversight. If I remove everything to do with the colour shifting, the text does display. The colour-shifting code is actually mostly copied over and then adapted from another part of the project (where it does work). The only thing I couldn't copy was a line which started "Result := ", so it's very likely that this line is what actually draws the hue-shifted bitmap. Adding "Result :=" here generates an undeclared identifier error, so I just left it out and hoped for the best. Clearly, though, I need something to explicitly say "draw the hue-shifted bitmap."
  14. My app uses mainly checkboxes for boolean values in the config menu. These are saved and loaded each time the app is closed and opened, no problem. However, one option calls for radio buttons rather than checkboxes, because it's a choice of 3 different things. If one is chosen, then the others can't be chosen. I use the same code to write the user's preference to the settings.ini file. However, when opening the app, the first radio button is always checked, regardless of what the user chose previously. Does anyone know if radio buttons require different handling than checkboxes when saving/loading the user input to/from a settings file?
  15. I can only apologise for this... It turns out it was all down to a simple typographical error 🤦‍♂️ I had LoadBoolean as 'Prefer A' instead of 'PreferA' - turns out that the spaces matter! So sorry, and thank you to all those who replied!! EDIT: A bonus outcome of this topic is that the code is now tidier and clearer; implementing this as a RadioGroup with an ItemIndex list rather than individual Radio Buttons is definitely better 👍
  16. Can you give an example of what you mean here? Also, how does this differ from the way I've set the Booleans already?
  17. Yes, this is what I'm doing. The problem is that it isn't loading the setting.
  18. OK, so I've tried doing this as a TRadioGroup instead, and I'm getting exactly the same problem: rgChooseSound: TRadioGroup; procedure TFormNXConfig.SaveToParams; begin GameParams.PreferA := rgChooseSound.ItemIndex = 0; GameParams.PreferB := rgChooseSound.ItemIndex = 1; end; procedure TFormNXConfig.SetOptions; begin if GameParams.PreferA then rgChooseSound.ItemIndex = 0; if GameParams.PreferB then rgChooseSound.ItemIndex = 1; end; procedure TFormNXConfig.SetChooseSoundRadioGroup(aValue: Integer); begin if rgChooseSound.ItemIndex = 0 then GameParams.PreferA; if rgChooseSound.ItemIndex = 1 then GameParams.PreferB; end; Then, in the GameControl unit: property PreferA: Boolean Index moPreferA read GetOptionFlag write SetOptionFlag; property PreferB: Boolean Index moPreferB read GetOptionFlag write SetOptionFlag; procedure TGameParams.SaveToIniFile; begin SaveBoolean('Prefer A', PreferA); SaveBoolean('Prefer B', PreferB); end; Procedure TGameParams.LoadFromIniFile; begin PreferA := LoadBoolean('PreferA', PreferA); PreferB := LoadBoolean('PreferB', PreferB); end; Can anyone see where I'm going wrong, and what I need to do to fix it? Using a RadioGroup and setting the options as list Items from an Index does work (i.e. it has the desired effect in-game), but the same problem of the choice not being remembered when the game is next opened occurs. It always resets to the first of the 2 options, every time. I need it to remember if the 2nd choice has been set, and load this. As far as I can see, my code is at least trying to do this, and I can't see where it's failing.
  19. Fixed this, it was a typo in the post. The code is as it should be. Yes, this is probably what I need to do. And this, too. So, it's looking like the way to handle options set by radio buttons is to group and itemindex them, like you would a dropdown list? @programmerdelphi2k Thanks for your examples, very helpful 🙂
  20. Yes, this is exactly what I'm trying to do. I can't figure out where my app is going wrong. The options are dealt with across 2 pas files, I'll paste the relevant stuff here: This is the actual config unit: unit FAppConfig; interface uses GameControl; type TFormAppConfig = class(TForm) rgChooseSound: TRadioGroup; rbSoundA: TRadioButton; rbSoundB: TRadioButton; procedure SetFromParams; procedure SaveToParams; implementation procedure TFormAppConfig.SetGameParams; begin SetFromParams; end; procedure TFormAppConfig.btnApplyClick(Sender: TObject); begin SaveToParams; end; procedure TFormAppConfig.btnOKClick(Sender: TObject); begin SaveToParams; ModalResult := mrOK; end; procedure TFormAppConfig.SetFromParams; begin fIsSetting := true; rbSoundA.Checked := GameParams.PreferSoundA; rbSoundB.Checked := GameParams.PreferSoundB; end; procedure TFormAppConfig.SaveToParams; GameParams.PreferSoundA := rbSoundA.Checked; GameParams.PreferSoundB := rbSoundB.Checked; end; end. Then, a separate unit to deal with saving and loading: unit GameControl; {------------------------------------------------------------------------------- The gamecontrol class is in fact just a global var which is passed through as a parameter to all screens. -------------------------------------------------------------------------------} interface type TMiscOption = ( moPreferSoundA moPreferSoundB ); property PreferSoundA: Boolean Index moPreferSoundA read GetOptionFlag write SetOptionFlag; property PreferSoundB: Boolean Index moPreferSoundB read GetOptionFlag write SetOptionFlag; implementation procedure AddUnknowns; begin SaveBoolean('PreferSoundA', PreferSoundA); SaveBoolean('PreferSoundB', PreferSoundB); procedure TDosGameParams.LoadFromIniFile; var SL: TStringList; function LoadBoolean(aLabel: String; aDefault: Boolean): Boolean; begin PreferSoundA := LoadBoolean('PreferSoundA', PreferSoundA); PreferSoundB := LoadBoolean('PreferSoundB', PreferSoundB); end; end. Whatever option I choose, the option is re-written as "PreferSoundA" when opening the app. This is even if SoundB is checked and written into the settings.ini file, i.e. When closing the app, the option will still say SoundB in the settings.ini. Then, I open it, and SoundA is checked again. P.S. This project is not mine, I'm working on an existing project which has sometimes very convoluted structure. Thanks for your help!
  21. I'm working on an existing application here, so I have no option but to work with the codebase that's already there. Very frustrating, I know, but that's why I'm taking to the Forums for help with this. Basically, I'm trying to display a background image. But that's not all. Currently, the image on the form is comprised of a number of different elements that get combined into a resizable bitmap (principally, the idea here is that the image will then look the same in terms of positioning/spacing/etc no matter how big the window is). One of these elements is the background. The problem is that the bitmap is set to an INTERNAL_SCREEN_WIDTH and INTERNAL_SCREEN_HEIGHT. So, if the window is improportionately sized (for any reason), we end up with empty horizontal (or vertical, depending on which way the window is sized) borders at the edges. If these INTERNAL_SCREEN values are meddled with, it causes all sorts of other problems with the display elsewhere in the app, so these can't really be changed. So, I want to separate the background from the combined bitmap image and display it independently, ideally tiling it across the actual background of the form, and then the remaining elements of the combined bitmap can display over it, scaling and resizing as normal. Then, the background image should - in theory - fill these empty spaces at the edges. Here's what the code looks like: procedure TGameBaseMenuScreen.InitializeImage; begin with ScreenImg do begin Bitmap.SetSize(INTERNAL_SCREEN_WIDTH, INTERNAL_SCREEN_HEIGHT); DrawBackground; BoundsRect := Rect(0, 0, ClientWidth, ClientHeight); ScreenImg.Align := alClient; ScreenImg.ScaleMode := smResize; ScreenImg.BitmapAlign := baCenter; end; end; Here's what I've tried: 1) Moving "DrawBackground;" to before Bitmap.SetSize in an attempt to handle the drawing of the background before the setting of the internal screen width & height. The app runs, but the background image isn't displayed at all (instead it's just a black background). All of the other elements are displayed as normal. 2) This: constructor TGameBaseMenuScreen.Create(aOwner: TComponent); begin inherited; DrawBackground; InitializeImage; ...etc So that DrawBackground is removed entirely from the "InitializeImage" procedure and run as a separate, independent procedure on creation of the menu screen. I get the same result (black background, other elements of the combined bitmap appearing as normal). I have no idea what else to try, or why I'm getting the above result from what I've tried so far. Any suggestions would be very welcome!
  22. This sounds promising, I'll see if I can figure out how to make this work with what's there.
  23. Yes, it is indeed a Graphics32 TImage32, apologies for not mentioning that previously. So, here's the current behaviour. The background image, menu items and logo all form part of a single bitmap which is generated and then displayed within the fixed internal screen boundaries: At present, my only options for increasing the size of the background image are to increase these fixed values, which causes all sorts of other problems elsewhere in the app (so, this is an absolute last-resort option which I probably won't do; I'd rather put up with the borders than mess with these values tbh.) The following is the desired behaviour. I want to display the background image completely independently, tiling it across the form and then displaying the menu bitmap on top of it: So now, the window can be resized and will always display the background. Meanwhile, the other menu items will always be centred according to the fixed internal screen values. Question is, how do I achieve this?
  24. I'm getting the E2137 error when trying to add a new procedure. Google result says it's usually to do with misspelling, but I used Ctrl + Shift + C to auto-create the code block (and double-checked the spelling), so that isn't the problem. Also, I would've thought that using Ctrl + Shift + C to auto-create the code block would put the block in the correct place in the unit, but apparently not. What other reasons could there be for this error? I can't copy out the entire code because the unit is huge (more than 2000 lines), but I'll try to just paste the relevant parts here: unit GameBaseSkillPanel; interface uses ... type ... private ... protected ... public procedure PanelResize; override; end; procedure TBaseSkillPanel.PanelResize; begin inherited; Width := GameParams.MainForm.ClientWidth; Height := GameParams.MainForm.ClientHeight; ClientWidth := GameParams.MainForm.ClientWidth; ClientHeight := GameParams.MainForm.ClientHeight; fImage.Width := GameParams.MainForm.ClientWidth; fImage.Height := PanelHeight; fImage.Left := (Width - Image.Width) div 2; fMinimapImage.Width := MinimapWidth; fMinimapImage.Height := MinimapHeight; fMinimapImage.Left := MinimapRect.Left; fMinimapImage.Top := MinimapRect.Top; end;
  25. Willicious

    E2137 Method not used in base class

    Yes, good advice. I can play piano and guitar (both of which took years to learn and master), so - in theory - a bit of programming shouldn't be too far beyond me. I am learning well, but some things just don't have answers without already knowing the codebase you're working with. Starting from scratch is so tempting, but the project I'm working on is already huge, it would likely take way longer to start it from scratch than it would to wrestle with the few features I'm trying to reverse-implement.
×