How do I make a background image scrollable with touch (with fixed overlaid buttons)?

0 favourites
  • 14 posts
From the Asset Store
Elevate your games with our AI Chatbot Integration! Seamlessly connect your Construct 3 projects with GPT-4 for dynamic,
  • Hi all

    I have a map screen that I want a user to be able to scroll around (on a mobile phone game). I've got a layout which is 4 times larger than the viewport, and set a background layer with my map image to this size.

    I've followed the tutorial here to use 8Direction and ScrollTo with an invisible sprite:

    construct.net/en/tutorials/add-smooth-scrolling-game-app-2292

    I don't really understand how this works to be honest! I've implemented it anyway... to get it to work (ish) I set the invisible sprite to be exactly the same size as the viewport (else it centres elsewhere and moves the background image so there's a white border), not sure if that's needed or I need to change the centre point or something... it only scrolls vertically (but I guess I can repeat for X values to make it scroll horizontally?) and carries on scrolling off the image (I guess I need to stop it somehow by checking a Y value?).

    It also scrolls pretty slowly. I tried increasing the x 3 number but that doesn't seem to make a difference.

    Is there another / a better / easier way to do this?

    I'd also want some fixed buttons / icons (i.e. sprites) overlaid on top of the map, they shouldn't move when the background map scrolls. Any pointers on how to do that also much appreciated!!

    Many thanks

    Ross

  • For your background: I'm not sure I fully understand what you are trying to achieve. The way I moved my background is by adding in my background image as a tiled background (not a sprite or regular background), and in my case, my background is always scrolling, so I set it to "Set image X offset to Self.ImageOffsetX-120 * dt", which makes it move to the left on its own at a set speed. You can accomplish something similar by tying this logic instead to the inputs to move the player and only move it when the player moves, if that's what you're looking for.

    As for the on-screen UI, you just have to give the things you want to stay locked on the layout the Anchor behavior, and they won't move no matter where you move.

  • Great, thank you! I don't have a player as such; it's just a large map screen so I want the user to be able to drag around and see the far corners etc. But that could be helpful, I'll look into the offset values and see if I can get it to respond to the touch in the right way.

    Thanks also for the note about Anchor, I did read about that only yesterday but was looking at general sprite properties for another part of the game and didn't click that would be ideal for the buttons on this screen :)

  • You don't need to use 8 direction or sprites, you can use the 'scroll to' action and some maths to determine your speed and direction.

    Create 4 static variables: TouchStartX, TouchStartY, TouchAngle, TouchDistance.

    1. 'On any touch start' you want to set the TouchStartX&Y variables to touch.X&Y

    2. 'Is in touch' you want to set the angle and distance variables to: angle(TouchStartX,TouchStartY,Touch.X,Touch.Y)-180 **-180 is to reverse the direction.

    distance(TouchStartX,TouchStartY,Touch.X,Touch.Y)

    As a sub event of 'is in touch' you can use the

    3. 'scroll to' action and set the values to lerp from the current scroll coordinates to the angle and distance of the touch action.

    lerp(scrollx,scrollx+cos(TouchAngle)*TouchDistance,1-dt*0.5)

    lerp(scrolly,scrolly+sin(TouchAngle)*TouchDistance,1-dt*0.5)

    4. 'On any touch end' reset all variables to 0.

    For your UI elements, create a new layer on top and set it's parallax settings to o. This layer won't be affected by any scrolling and your buttons and text will remain in place relative to the viewport.

  • Since the map sprite is the same size as the layout you can do this. Make the map sprite's origin be at the top left, give the map sprite the drag and drop behavior, and finally add this event to limit how far you can drag the map.

    every tick: map: set position to clamp(self.X, OriginalWindowWidth-LayoutWidth, 0), clamp(self.Y, OriginalWindowHeight-LayoutHeight, 0)

  • Thanks all!! I stumbled across the "drag and drop" behaviour method yesterday evening and have been tinkering; I've been using a check on every tick to see if the X and Y positions went beyond the borders (using negative values) and re-setting and this worked, but oddly not to the perfect numbers (0 and layout width/height - viewport width/height) - I was getting white borders top and right, and not scrolling far enough left and down.

    I've fixed this morning by tweaking the numbers (by 30 or so pixels each side) but didn't understand why!

    Just saw these posts... thought I'd try R0J0hounds "clamp" command (not come across this one before, thanks!) and unfortunately I get the same white border issue. I've checked my numbers again:

    layout 960 x 1708

    viewport 480 x 854

    -i.e. width and height wise it's half half / viewport is a quarter of the layout exactly.

    Background map image is exactly the same size as the layout.

    So... why the white borders?!

    Not a huge issue, as I can get by it with my checks & sets, be good to understand why though.

  • Well if you didn’t change the camera scroll from the top left, and the origin of the sprite map’s image is top left then it should work from my tests. Did you check the origin?

  • Thanks again! Something has gone wrong with my original layout and/or event sheet - just created new ones and works perfectly!

    WELL... the map image scroll does...

    BUT it doesn't work as intended for the "town" sprites I want to scroll in place of the map - need to "bind" them somehow to the background map image or background layer, can't figure out how - any suggestions please? Changing the town sprite behaviours (Pin, Anchor, Scroll To, Bound to Layout, Drag & Drop) hasn't helped.

    Maybe I need to re-position the sprites relative to the background map sprite on each tick too...?

  • You can use the pin behavior oh the objects you want to move with the map, and pin them to the map sprite.

    Alternate idea is to set the scroll instead similar to the other suggestions.

    I like to try to simplify stuff so calminthenight’s solution probably could be simplified a bit further to something like this. I haven’t had a chance to test it.

    Var prevX
    Var prevY
    On touch
    — set prevX to touch.x
    — set prevY to touch.y
    Is touching
    — scroll to scrollx+prevX-touch.x, scrolly+prevY-touch.y
    — set prevX to touch.x
    — set prevY to touch.y
  • Thanks again! I'd set Pin behaviour but not actually pinned the sprite to anything; now set an on layout start event to pin it to the background map - IT WORKS!!!

    Indeed, calminthenight’s solution was what I was going to try next so if I have any further problems will try / check out your simplified version.

    Thanks all!

  • Try Construct 3

    Develop games in your browser. Powerful, performant & highly capable.

    Try Now Construct 3 users don't see these ads
  • Trust in ROJO. I'm sure the simplified version of my response will work.

  • Hey guys... sorry, stuck again!

    The drag & drop map position from ROJO worked well, until I tried to scroll to a sprite, basically a map marker of where the user currently is. Want the map to start off centralised where the user is.

    For some reason, if I do that on layout load (even with a 0.5 sec delay) it messes up the edges and I then cant scroll far enough left, and it goes too far right...if its a manual button press action it works, but not well - if the sprite is out of the viewport it only scrolls to the far edge of the sprite.

    So, I tried the simplified calminthenight code from ROJO - works! Doesn't mess up the edges when I use "scroll to", and nicely puts the marker in the centre!

    BUT...

    That code doesn't restrict the edges at all, and you can scroll right off the map...

    I tried using clamp, and now have this:

    This does limit the scrolling but goes way off the edges still - I think it's to do with "scroll to"'s behaviour and the centre camera? The scroll to seems to put the sprite exactly in the centre of the view so is there another half distance x and y or something like that I need to factor in..?!

    TIA!

    Ross

  • Make sure you don't have the unbounded scrolling option selected in the layout properties. Shouldn't need clamp if map is same size as layout.

    This code works fine with unbounded scrolling off.

  • You're right - it's my fault! Realised this morning that I'd left the Drag & drop behaviour enabled from the previous method; that was messing it all up. Removed that behaviour and set the code back (without clamp) and it works.

    Brilliant, really appreciate the help! Only started with Construct 3 about 2 weeks ago now but I (think!) I'm getting a good grasp of it and can do about 90% of what I need to do now :)

    Cheers!

Jump to:
Active Users
There are 1 visitors browsing this topic (0 users and 1 guests)