Pixcade - Web Monetization Gamejam 2020

I’ll be participating in the upcoming Web Monetization Gamejam for 2020 and before it starts I want to test out some of the services I plan to use. I will make a game on my own as well as mentor a few friends on Defold to make some small games for the jam.

One week away from starting as of this post!

In this thread I will document various things about the process of preparation for the jam as well as how games progress throughout the jam.

A couple of things I want to practice with / figure out how to do before the gamejam starts:

  • An easy and reliable way to validate web monetization receipts. I want a stupidly simple solution. Like as simple as Google or Apple receipts are to validate.
  • Using PlayFab. Recently they lowered prices and changed it to pay as you go. I only briefly tested it in the past. It’s good to roll your own service since it’s so easy and cheap but PlayFab now that Microsoft owns it and its part of Azure I feel confident in using it since so many other games use it and it doesn’t seem likely to be discontinued. So using it on smaller projects, test projects seems fine since you don’t have to maintain the servers for it. The main things I want to test with PlayFab are login stuff / saving and loading / playing the game on multiple devices / testing currency features / testing payment features (like using PayPal on HTML5 builds to buy currency in game). I want to have a payment option as a possible thing besides Web Monetization so that people can get benefits for both.
  • Can PlayFab be used to validate web monetization receipts within CloudScript (JavaScript)? CloudScripts are limited by total size so it doesn’t seem like a good idea to try and include it here. It feels like it would be way better if there was a public, trustworthy authority to validate through then it could be a simple HTTP request to check receipts. It’s hard to tell the right way to do this.
  • Test a rewarded video monetization option for HTML5. Admob is supposed to have an option for this but they never gave me an invite. I will ask around and investigate options. It seems like the options that are out there have very high user requirements before they even bother allowing you to use them, unlike mobile options.

Some other preparation I’ll be doing is setting up the Pixcade site a bit more. Here are some simple design mocks:

For the people I am mentoring, we will try to get the games to full commercial polish level even if they are simple, and then publish them on the Pixcade site within the period of the jam with other platforms potentially happening after. Right now I have 3 people and we’ll see what the follow through comes to.

7 Likes

Regarding PlayFab and OAuth.

  • Twitch version example is broken. I think I could get it to work by doing some steps manually so will have to experiment with that more later.
  • PlayFab doesn’t have Twitter OAuth which I wish it did have.
  • Facebook OAuth seems straight forward. However it requires business verification stuff I think which I don’t have setup for Pixcade, I might be wrong, need to test and see.
  • Google OAuth also is straight forward. In the case of Google OAuth is it’s annoying to setup custom support e-mail addresses to show, I’m not atm sure how to do that for Pixcade without paying money which is annoying.

I’m not going to mess with OAuth more for now though but maybe after the gamejam I’ll add more of the others, it’s nice that you can add others after. Using e-mail + password will be what I do use along with a guess account system that gives them an incentive to upgrade to a full account.

While doing some research on PlayFab again I looked at AdVenture Capitalist again and am surprised to learn that they did not use PlayFab for saving / syncing user data… this seems like a mistake. But they did get value out of it. PlayFab has some features which can help you improve monetization clearly.

I posted on the Coil receipt validation Github page and also learned some more about it

https://github.com/coilhq/receipt-verifier/pull/19
https://github.com/coilhq/receipt-verifier/issues/20

sabinebertram there mentioned this which should be able to be used to at least test receipt verification I think, but it is not suitable for production. I still want an EZ solution too and I think if that group can make one it will help with adoption.

https://ilp-torrent.sabinebertram.com/verifier-app/

Testing PayPal HTML5 payments via PlayFab is next on my todo list for this. I want to test doing

  • Full version unlock IAP
  • Disable ads IAP (ads also disable when buying anything else? I’m sure a CloudScript could be setup to do that)
  • Refresh energy IAP
  • Buy currency IAP

PlayFab has features which can help setup all of these. The full version unlock and disable adds would maybe be adding things to the user’s inventory, refresh energy would be a currency (you can setup currencies which auto regenerate over time, and still allow buying more of it to go above the max), and buying currency would just be like buying gold/gems.

I’ll be testing PlayFab’s coupon system for all of the IAP stuff too.

For Web Monetization until we have reliable receipt verification I think I will do only two things:

  • Disable ads (which means buying the IAP is not required)
  • Flat %/X bonus to things, so like it could mean earing more XP or more gold as a bonus thanks to having WM enabled

Once receipt verification is in place I will want to test having a currency be granted in accordance (with a multiplier to incentivize it) with the amount of value being paid through WM. So it can be kind of like a pseudo paid subscription with passive trickle value as you play.

PlayFab doesn’t support PayPal sandbox? https://community.playfab.com/questions/5228/having-issues-with-playfab-and-paypal-only-in-the.html

Hit a dead end with implementing PayPal

PlayFab not authorized to perform actions on given PayPal account.

I did setup the permissions but it did not help.

Next, set up the third-party permissions in PayPal so that we can act on your behalf. For live payments, set your account to allow “billing_api1.playfab.com” to process Express Checkout payments.

Here is the very ugly test code so far

function init(self)
	local loginRequest = {
		-- https://api.playfab.com/Documentation/Client/method/LoginWithCustomID
		CustomId = "TestCustomId",
		CreateAccount = true
	}
	PlayFabClientApi.LoginWithCustomID(loginRequest, 
		function(result)
			print("Login Successful: " .. result.PlayFabId)
			local account_info_request = {}
			print(PlayFabClientApi.GetAccountInfo(account_info_request,
			function(result)
				pprint(result.AccountInfo)
				print("UID:" .. result.AccountInfo.PlayFabId)
				local start_purchase_request = {
					Items = { 
								{ItemId = "test-item-one-cent", Quantity = 1, Annotation = "Purchased via in-game store"}
							}
				}
				PlayFabClientApi.StartPurchase(start_purchase_request, 
				function(result)
					pprint(result) 
					local purchase_request = {
						OrderId = result.OrderId,
						ProviderName = "PayPal",
						Currency = "RM"
					}
					PlayFabClientApi.PayForPurchase(purchase_request, function(result) pprint(result) end, function(error) pprint(error) end)
				end,
				function(error) pprint(error) end)
			end, 
			function(error)
				pprint(error)
			end))
		end,
			
		function(error) 
			print("Login Failed: " .. error.errorMessage)
			
		end)
end

For me this ends in

{ --[[000002CBF87A5800]]
  error = "FailedByPaymentProvider",
  errorCode = 1015,
  code = 400,
  status = "BadRequest",
  errorDetails = { --[[000002CBF87A5AB0]]
    ProviderOrderId = { } --[[000002CBF87A5D80]],
    ProviderErrorCode = { --[[000002CBF87A5B00]]
      1 = "1"
    },
    ProviderErrorDetails = { } --[[000002CBF87A5CC0]],
    ProviderErrorMessage = { --[[000002CBF87A5BD0]]
      1 = "Error: 10002 - Authentication/Authorization Failed"
    }
  },
  errorMessage = "PlayFab not authorized to perform actions on given PayPal account."
}

Maybe someone else can experiment with that, or if they already have it working give notes on what was done differently.

I cannot appear to be able to delete the option for PlayFab no matter where I look to see if redoing it helps

I tried setting the Real Money price to 100 instead of 1 and did not help.

Found where to remove the PlayFab option

https://www.paypal.com/businessmanage/credentials/apiaccess

Manage API Permissions

billing_api1.playfab.com

Although I removed it without checking the permissions it had listed.

Added it again with the 2 express payment options and it didn’t work still. Tried giving it way more permissions and it still is not working. Possibly it’s a delay thing so I’ll try again later after it has time to decide to work or not.

Success! So maybe when I added their id before I forgot to add the right permissions related to express cart. I also tried redoing the addon on PlayFab so that might have helped to refresh it.

DEBUG:SCRIPT: 
{
  OrderId = "XXXXXXXXXXXXXX",
  Status = "Init",
  PurchasePrice = 100,
  PurchaseCurrency = "RM",
  ProviderData = "XXXXXXXXXXXXXX",
  PurchaseConfirmationPageURL = "https://www.paypal.com/webscr?cmd=_express-checkout&useraction=commit&token=XXXXXXXXXXXXXX",
  VirtualCurrency = { } ,
  CreditApplied = 0,
  VCAmount = { } 
}

https://docs.microsoft.com/en-us/gaming/playfab/features/commerce/economy/non-receipt-payment-processing

I believe this should also work to allow doing IAPs within desktop games. You would open the PurchaseConfirmationPageURL with sys.open_url() wait for user to finish transaction, and then wait on PlayFab to confirm it’s finished. Would need to test to be sure.

Yes! It can be done on desktop games too not just HTML5 I tested the entire flow.

{ 
  PurchaseDate = "2020-10-27T05:37:03.88Z",
  Items = { 
    1 = { 
      Annotation = "Purchased via in-game store",
      DisplayName = "Test Item 0.10 USD",
      PurchaseDate = "2020-10-27T05:37:03.88Z",
      UnitPrice = 10,
      UnitCurrency = "RM",
      CatalogVersion = "Tests",
      ItemClass = "test",
      ItemInstanceId = "XXXXXXXXXXX",
      ItemId = "test-item-one-cent"
    }
  },
  OrderId = "XXXXXXXXXXX"
}

Fun fact: PayPal takes everything from micro payments like ones at $0.10 there might be some setup you can go through where they don’t do that though it’s not this one.

I refunded the 10cents after we tested. :smiley:

Based on these fees it seems like even charging $1 for something is a dumb idea, better to go higher if you have give the value to the player where they feel it’s worth the price.

At the moment I’m confused as to where the PayPal Transaction ID is on the PlayFab side after a purchase is made. Need to test this more to see which IDs line up.

Another thing I need to test is the return link from PayPal / setup the flow for it to be nice.

Current ugly test code

function init(self)
	local loginRequest = {
		-- https://api.playfab.com/Documentation/Client/method/LoginWithCustomID
		CustomId = "TestCustomId",
		CreateAccount = true
	}
	PlayFabClientApi.LoginWithCustomID(loginRequest, 
		function(result)
			print("Login Successful: " .. result.PlayFabId)
			local account_info_request = {}
			print(PlayFabClientApi.GetAccountInfo(account_info_request,
			function(result)
				pprint(result.AccountInfo)
				print("UID:" .. result.AccountInfo.PlayFabId)
				local start_purchase_request = {
					Items = { 
								{ItemId = "test-item-one-cent", Quantity = 1, Annotation = "Purchased via in-game store"}
							}
				}
				PlayFabClientApi.StartPurchase(start_purchase_request, 
				function(result)
					pprint(result) 
					local purchase_request = {
						OrderId = result.OrderId,
						ProviderName = "PayPal",
						Currency = "RM"
					}
					PlayFabClientApi.PayForPurchase(purchase_request, 
					function(result)
						pprint(result)
						-- repeat checking purchase
						sys.open_url(result.PurchaseConfirmationPageURL)
						timer.delay(10, true, function(self, handle, time_elapsed)
							local confirm_purchase_request = {
								OrderId = result.OrderId
							}
							PlayFabClientApi.ConfirmPurchase(confirm_purchase_request, 
							function(result)
								pprint(result)
								if result.PurchaseDate then
									print("Purchase went through fully!")
								end
							end, 
							function(error)
								pprint(error)
							end)
						end)
					end, 
					function(error) pprint(error) end)
				end,
				function(error) pprint(error) end)
			end, 
			function(error)
				pprint(error)
			end))
		end,
			
		function(error) 
			print("Login Failed: " .. error.errorMessage)
			
		end)
end

There are a bunch of transaction states and they will need to be handled properly. I’d guess it may be possible to run different CloudScripts when transaction state changes to decide what to do, like what to do when handling a refund or chargeback if you want to do that automatically.

4 Likes

2 days until the gamejam begins. People are feeling hyped and want to know the theme! I hope it’s a fun one. :sparkles:

I have prepared the next Pixcade site template though have not uploaded it yet. It’s responsive / simple / all that’s really needed. On Pixcade the games will follow the pattern of pixcade.com/game where the game is playable as an iframe (and has banner ads) and then pixcade.com/game/web will be a perfect fit fullscreen version that is what is iframe embedded (and has interstitial / rewarded video ads).

Usually I do not like including features like Google Analytics on my sites but for Pixcade we will use it since partners want to be able to see that data collected by a 3rd party and for Pixcade I want to help people get games going and get partners interested.

I reached out to a few rewarded video options for HTML5 games but only one replied so far. They are https://adinplay.com/ and so I’ll be testing their features first. They had me setup this file https://www.pixcade.com/ads.txt and am still waiting on ad unit code. It’s done through https://support.google.com/admanager/answer/9059370 I don’t know everything about how it works yet. If the user has Web Monetization enabled it will set a cookie/file in local storage and then if that is set on the domain every page will strip all ad displays like banner ads on the game pages. I want to test putting rewarded video ads everywhere in the games to the point of being annoying like a lot of the top F2P mobile games currently do. I want to balance that with a test game where there are only premium Real Money offerings and no in game ads at all. There are mobile games where you would think they would benefit from having rewarded videos in their games, but they don’t have them. I suspect it’s because they want to keep the users in their games, and it’s better to not push them out just for a few cents, better to keep them there and go for getting a few $$$.

Regarding ads, if anyone remembers Project Wonderful if other ad options don’t work out well I may make a self-service ad solution for Pixcade. That is anyone can sign up on the solution, then they can bid on ad space in any specific game they want to place ads on. Banner ads / rewarded video ads / and so on. If Pixcade takes off this will be worth investing in.

I’ll be using BunnyCDN again for this, used them before and no complaints. Reliable and inexpensive. I’ll be uploading versions of games to the Pixcade.com domain as well as itch pages for it.

If you participate in the jam make sure you domain / protocol lock your game. Domain Lock HTML5 games I’ll post again about this soon with an up to date version. For example, making it easy to include a list of partner domains who license your game for embedding on their site that don’t require editing the game itself to update.

Regarding PlayFab I’ve explored its features a bunch more. Tested the crucial questions I had initially. I’m confident in using it without any foreseeable problems… except that PayPal Transaction Ids are not lining up for me in my testss, waiting to hear back from them on that. I’ll share some more info about PlayFab in future posts such as related to Cloud Script patterns, gacha roll systems, and anything people have questions on hopefully I’ll be able to answer now.

3 Likes

A note from PlayFab

The TransactionId in the player_realmoney_purchase event is the “Transaction ID” + “@@@” + “the payer ID” we get from PayPal.

I’ll need to do more test transactions to see if any of them line up.

Live estimated USD paid counter! Maybe it will encourage people who have WM installed to play more / pay more.

The gamejam has begun! I like the “secret” theme especially as there are many useful ways to interpret it.

As far as secret+WM goes I think an obvious feature to unlock for those who have WM enabled would be a guidebook / hintbook that gives walkthroughs toward unlocking the secrets / mastering the game. Then could have it so that people who don’t have WM enabled can watch a rewarded video ad to unlock specific pages of a book.

spoilers

For the secret theme, the first thought I had game wise would be to make a 3d puzzle box game. What I mean is like what this guy solves on his YT channel. A 3d version could do things you can’t do in the real world, but the real puzzle boxes also have charm from the physical nature of them. You could have a lot of optional secrets / hints toward the path of reveal a puzzle box’s final secret. This kind of concept wouldn’t have to be 3d either, it could be in a 2d space, like imagine a room with box2d physics and and you can click and drag to move stuff. As you interact with the room, hopefully based on logical progressions, you use up physics items to unlock more of them toward progressing something to a final state. I think these kinds of ideas could be compelling enough. I think The Room mobile game is kind of a 3d puzzle box concept?

Another obvious idea is the escape the room concept, which is done in the real world, and is also a genre popular in games.

I will hopefully be making 3 games this jam one by myself and then 2 others with 2 other people I’m trying to convince to start using Defold.

2 Likes

I tried PayPal with Playfab again today and the transaction IDs on PayPal vs Playfab still did not line up. Playfab says to ask PayPal about it, but it seems like something wrong on the Playfab side. It would be helpful if anyone else with an interest in Playfab could test doing a PayPal transaction and seeing if the IDs line up or not. If you want to try and have any questions let me know.

Without the IDs lining up properly between the player_realmoney_purchase and the Transaction ID on PayPal for the purchase, it means I can’t properly ban people who charge back to disincentivize that costly behavior, and I can’t as easily give refunds if need be without asking people for their PayPal transaction ID. It also means I can’t look up what a transaction ID is a purchase of which is annoying for certain categories of IAPs, like consumables you don’t want to allow refunds if consume what they buy because that’s asking for trouble, if you refund someone who consumes something you have to then also ban them. For doing refunds I think I’d have to ask for all of their Transaction IDs and their PlayFab ID, then look at the history of the PlayFab ID to see if the purchase times line up to know what is what if some things are priced the same. Doable but very annoying and requires honest cooperation… It would still be possible to ban chargeback accounts but it would require manually looking through real money purchase events for the exact timestamps for the purchase values. Really having the IDs line up properly simplifies everything. :innocent:


While thinking about ideas more I’m doing some more setup work for some general features and design stuff. For bare bones implementation of games I’ll only do the core game + site lock + simple WM unlock / ad disable + rewarded video and none of the side stuff. Then if I have time I’ll expand and do other things I want to such as guides.

For removing ads, if WM ever runs / anything is every purchased that would disable ads, I’m doing something like this to remove the banner ads, and since adinplay allows you to easily spawn the ads I will check the localstorage entry first and not spawn the ads if the value is set.

<script>
localStorage.setItem('ads_disabled', "false");
//localStorage.setItem('ads_disabled', "true");


function removeElementsByClass(className){
	var elements = document.getElementsByClassName(className);
	while(elements.length > 0){
		elements[0].parentNode.removeChild(elements[0]);
	}
}
// Yes, this is really simple! Using adblock is too. (:
if (localStorage.getItem('ads_disabled') === "true") {
	removeElementsByClass("ad_unit");
}

</script>
3 Likes

I’m curious about Paypal integration for HTML5.

Is it like a pop-up window for Paypal to process the payment, so the game itself is not interrupted?

Or does it redirect to a Paypal page (interrupting the game), then once Paypal is done, it redirects back to the game (forcing a game reload)?

You get a link from PlayFab for the PayPal transaction to begin once you start the store purchase process. You decide how to handle this link.

You can then open this url in the browser in a new target window, that way the game is not interrupted.

After PayPal is done with the payment it has a return URL you define on PlayFab for the title. This could be your game link or another generic page. There are post fields to this URL so you can tell if the transaction was successful or in error.

In the game itself you will want to periodically check if the transaction is complete (and give the user an option to cancel). I would do it on a timer that is at least 10 seconds long each check, but doing additional checks when the game is in focus again is a good UX most likely.

If you did want the game to be interrupted it would be possible to do. You’d want to save the transaction info so the game could look it up once it got focus again. In that case you would want your return URL to be your game or your return URL to link to your game.

3 Likes

Thanks for the info! :smiley:

1 Like

Since this gamejam is based on secrets, I’ll be marking the actual game design in my post as spoilers within [details] blocks. If you read these blocks before you’ve played you may have less enjoyment. :secret:

I’ve decided on a design I like (basically an idea from above… which was an obvious choice for me but also something I really like so I’m going to go for it anyway even if it might not be very original) for my personal game and minimized it to a simple core. After I get the core done I’ll work on additional ideas I want to add.

One of the things I’ll do after core is to add orientation agnostic UI. I plan to have the main game area in a square, and then the UI to float in a 960x640 or 640x960 area depending on orientation. And then the other area can be buffer for banner ad space if there is enough safe area on the resolution of the device. I can then detect the orientation on the HTML5 page and give the best option for the user there. Same for mobile version. It will be good practice.

Here are some images to illustrate what I’ll try to do. The pink area is the 960x640 or 640x960 area. The grey the main interactable area. The yellow the inventory area. The white arrow misc/pause UI position. The green an example of extra area from a phone, in this case my phone.

Below is a sketch ref of what the actual game may look like.

spoilers

The idea is that there are various squares you can unlock and each has a different puzzle. The squares have things you can interact with, though some things may be unlocked. As you progress the game, you can unlock items to add to your inventory. These items may be one time use, or items which have infinite use. I want some physical quality for interaction with sometimes multiple ways to solve a puzzle? So for dealing with ice if you have a heat source you could melt ice, or you could grab the frozen thing and smash it against the wall until it shatters.

These kinds of intuitive puzzles that have a physical quality. Plus more things that are secret! The way I intend to do the physical interactions is to use the Box2D features mostly. In some cases it could be applying forces based on touch, others may be messing with joints. I’ll try to make one simple puzzle square once as the MVP. The project as a whole will have items you can add to your inventory which can help you solve optional parts of earlier squares, which may unlock items needed elsewhere too. So it can have some item trading like progressing as optional progression. Along with hidden things. Did I give too much away already? :smiley:

3 Likes

This post has progress on basic implementation.

spoilers

https://www.youtube.com/watch?v=REFBO6tEsEs

Something I need is the mouse cursor joint of Box2D to get the non-bouncy spring grab that I want.

Another thing which I believe would be useful would be to be able to do raycasts inside of collision hulls, that way I would not need to use a tiny collision object for the cursor and deal with the problems it creates.

But even with both of these I feel I can still make a decent MVP so I’m going to continue with that.

Next steps for me is to polish up the feel more. Then I will clean up the project and try to make some of the puzzle interactions.

One useful thing I am doing is instead of having a ton of physics mask ids I am using only a single one for general objects: entity. Then for entity objects I add a script with go.property(“entity_id”, id) and when doing collisions / grabbing I’ll check this entity id based on collisions to decide what to do with interactions. This means I can have as many unique ids as I want without running out of physics masks.

1 Like

The more I use PlayFab the more I want to not use PlayFab because even though it makes some things easy and simple other things are harder and more complex than they need to be because PlayFab was designed to be “as efficient as possible” while also being easy and simple for many types of things. For example, it’s designed to be transactional, not to keep a socket open at all time, and it doesn’t want you to do that much communication with the service that often. I would much rather prefer to always have a socket open, and transfer data back and forth as needed without worrying about going over doing 1 per minute. I’m sticking with it for now but it’s really tempting to roll something custom and self host it. If I get serious with Pixcade I will switch to custom because some cool things that I’m interested in will require custom servers anyway. Maybe down the road I will make something similar to PlayFab but allows persistent connections, works with multiple games at once, and is easy to self host for anyone.
:thinking:

Game jam progress wise next few days I’ll be dedicating to making big progress on my personal game. Other two games have not made much progress, trying to motivate people is hard. :slight_smile:

Right now it looks like one of them will be a mini visual novel, the other will be a mini idle game.

Once my physics game is 100% playable I will try to make this feature and get it working, I did read all of the related source and it seems reasonable, but I still have not got the engine / editor to build (only tried once months ago and hit a wall) so that is a time sink I will have to try to go through again first.

Design wise for my game I am making a few decisions. The game will have levels you can advance through forward only, keep it simple, keep number of menus and so on super minimal. The game will have an IAP to buy that is also unlocked with WM that is a hint tool done in a cool “secret” way. I’ll also have rewarded video ads to unlock the hint tool one level at a time so there will be 3 ways to unlock the tool.

I have new Pixcade site design mostly good to go as far as releasing something goes.

I did some exploring around WM tech more. https://www.pumabrowser.com/ allows WM on mobile.

<html>
<head>
<meta name="monetization" content="$ilp.uphold.com/QkG86UgXzKq8" note="Defold Foundation" />
</head>
<body>

<div id="puma-mobile-promo"></div>

<script>
function pumaMobilePromo() {
    if (/mobi/i.test(navigator.userAgent) && document.monetization === undefined) {
        document.getElementById("puma-mobile-promo").innerHTML = "Get the <a href='https://www.pumabrowser.com/'>Puma Browser</a> for Mobile Web Monetization Multipass support.";
    } else {
        document.getElementById("puma-mobile-promo").outerHTML = "";
    }
}
pumaMobilePromo();
</script>

Above is a snippet to promote the Puma browser for mobile users.

I pinged more ad companies and mostly nothing good to say but my experience with AdinPlay has been great and I recommend them. I’ll be using them for rewarded video and interstitial ads.

I am going to be referring to Web Monetization provider subscriptions as a Web Monetization Multipass or Multipass for short and I recommend others do the same. :wink:

4 Likes

Getting the dynamic UI to work was easy. Like many things in Defold the layouts / dynamic orientation / display profiles system is magic. It only took a few minutes for me to set this test up so it works and only required a minor builtin render script modification to know when the display orientation changes.

A cleaned up version of this test should be a builtin template IMO to show these features, make it a fork of the mobile template.

1 Like

Thanks to a Defold contribution by @dapetcu21 in the upcoming 176 adding extra divs or other elements above the canvas in fullscreen mode is easy.

These will be used for the rewarded video / interstitial / banner ads on HTML5. I have an accurate measurement for the free space around the game depending on orientation, so I know if I can safely display banner ads around the game while in fullscreen mode and will also dynamically hide/show them as the window is resized. This is with a centering of the game, if I want to always be able to safely display banner ads I would have to offset the center of the game and potentially scale it down too but I’m not going to do that at least for this project.

3 Likes

Oh! Awesome! I’m glad it was useful to someone else :slight_smile:

3 Likes