2016年1月25日 星期一

[게임] 바둑 - 사활 문제 APP


Android 해제

iOS 해제

이 응용 프로그램은 사활 문제의 100 개 이상의 운동을 포함.
그들 모두는 무료입니다.
사활 문제는 이동 게임에 매우 중요하다.
게임을이기거나 할 수없는 경우 사실, 결정할 수있다.

모든 운동을 완료하기 위해 서둘러하지 마십시오.
당신이 다음 운동에 가기 전에 모든 가능성을 확인합니다.
이 응용 프로그램은 모든 운동을 몇 번 통과하는 경우는 경력이 속도를 증가하는 데 도움이 될 것입니다.
의 함께 진행을하자 ...






[ゲーム]囲碁 - 詰め碁演習APP


Androidのバージョン

iOSのバージョン

このアプリは、詰め碁の100以上の練習問題を含んでいます。
それらのすべてが無料です。
詰め碁演習はのため囲碁のゲームは非常に重要です。
実際に、それはあなたがゲームに勝つことができるかどうかを決定することができます。

すべての演習を完了するために急いでしないでください。
あなたは次の演習に進む前に、すべての可能性をご確認ください。
このアプリは、あなたがすべての演習を数回通過する場合は、勝率を高めるのに役立ちます。
ご一緒に進捗状況を取得してみましょう...





[ 游戏 ] 围棋 - 死活练习手游APP


Android 版本

iOS 版本

这个APP包括超过上百个死​​活练习题目,
所有题目都是免费就可以练习。

死活问题对于围棋来说很重要,
事实上,它可能会决定你是否能在下棋时获胜。

不要急着把所有练习一次做完,
在进到下一题之前,先把目前题目所有可能的变化都演练一次,
这对于提升你的棋力很有帮助。
让我们一起努力吧....




[ 遊戲 ] 圍棋 - 死活練習手遊APP


Android 版本

iOS 版本

這個APP包括超過上百個死活練習題目,
所有題目都是免費就可以練習。

死活問題對於圍棋來說很重要,
事實上,它可能會決定你是否能在下棋時獲勝。

不要急著把所有練習一次做完,
在進到下一題之前,先把目前題目所有可能的變化都演練一次,
這對於提升你的棋力很有幫助。
讓我們一起努力吧....





2015年11月17日 星期二

[Corona SDK] How to support multiple Ads networks - AdMob, iAds, Vungle

InHow to add advertisement in my APP - using AdMob V2, we learn how to add AdMob Ads.
For iAds and Vungle, we can use the similar way to add them.
We just consider how to support multiple networks here.
That it, we want to select AdMobiAds or Vungle dynamically, no matter it is for Fill Rate, eCPM or any other reasons.

Add plugin
First, we need add plug-in in build.settings:
settings =
{
 plugins =
    {
       ["plugin.google.play.services"] =
        {
            publisherId = "com.coronalabs"
        },
        ["CoronaProvider.ads.iads"] =
        {
            publisherId = "com.coronalabs",
            supportedPlatforms = { iphone=true, ["iphone-sim"]=true },
        },
        ["CoronaProvider.ads.vungle"] =
        {
            publisherId = "com.vungle",
        },      
    },
 android =
    {

        usesPermissions =
        {
            "android.permission.INTERNET",
            "android.permission.ACCESS_NETWORK_STATE",
        },
    },
}


Init the Ads
local adsProvider = {"adMob1","adMob2","vungle","iAds"} 
local ads = require( "ads" )
local adMobAdProvider = "admob"
local iAdsAdProvider = "iads"
local vungleAdProvider = "vungle"
local vungleAppId = "55e4xxxxxx"
local bannerAppID = "ca-app-pub-xxxxxx"
local interstitialAppID = "ca-app-pub-xxxxxx"
local appID = "com.gmail.MyCompany.App"
if ( isAndroid ) then
    bannerAppID = "ca-app-pub-xxxxx"
    interstitialAppID = "ca-app-xxxxxx"
    vungleAppId = "com.gmail.My_Company.App"
end
local lastAdsTypeShown = "none"
local currentAds = 1

local function adMobListener( event )
    local msg = event.response
    -- Quick debug message regarding the response from the library
    print( "Message from the adMob library: ", msg )
 if (event.type == "banner") then
     if ( event.isError ) then
         changeToNextAds()
     else
     end
 elseif(event.type == "interstitial") then
        if ( event.isError ) then
            changeToNextAds()
        elseif ( event.phase == "loaded" ) then
        elseif ( event.phase == "shown" ) then
        end
 end  
end

local function iAdsListener( event )
 local msg = event.response
 print("Message received from the iAds library: ", msg)
 if event.isError then
  changeToNextAds() 
 else
 end  
end

local function vungleListener( event )
   print("Message received from the vungleListener library: ", event.type)

   if ( event.type == "adStart" and event.isError ) then
     changeToNextAds()
   elseif ( event.type == "adEnd" ) then
      -- Ad was successfully shown and ended; hide the overlay so the app can resume.
   else
      print( "Received event", event.type )
   end
   return true
end

function adsInit()
 ads.init( adMobAdProvider, bannerAppID, adMobListener )
 if(isAndroid == false) then
   ads.init( iAdsAdProvider, appID, iAdsListener )    
 end
 ads.init( vungleAdProvider, vungleAppId, vungleListener )
end
We have to call ads.init() for AdMob,iAds and Vungle separately.
The parameters in their callback functions are different.
In above codes, we change to next Ads network when we get error.

Change Ads Network
We set new Ads network by function ads:setCurrentProvider().
local function changeToNextAds()
 currentAds = currentAds + 1
 if(currentAds > 3) then
  currentAds = 1
 end
 if(adsProvider[currentAds] == "iAds") then
  ads:setCurrentProvider(iAdsAdProvider)
 elseif(adsProvider[currentAds] == "vungle") then
  ads:setCurrentProvider(vungleAdProvider)
 else
  ads:setCurrentProvider(adMobAdProvider)
 end
end


Show Ads
function showAds(type,px,py)
 if(adsProvider[currentAds] == "adMob") then
  if(type == "banner") then
   ads.show( type, { x=px, y=py, appId=bannerAppID} )
   return true
  elseif(type == "interstitial") then    
   if(ads.isLoaded(type))then
    ads.show( type, { x=px, y=py, appId=interstitialAppID } )
    return true
   else
    return false
   end 
  end 
 elseif(adsProvider[currentAds] == "vungle") then
  if (type == "interstitial" and ads.isAdAvailable() ) then
      ads.show( "interstitial" )
      return true
  else
   return false
  end   
 elseif(adsProvider[currentAds] == "iAds") then
  ads.show( type, { x=px, y=py} )
  return true
 end
 return false  
end

function loadAds()
 if(adsProvider[currentAds] == "adMob") then
  ads.load( "interstitial", { appId=interstitialAppID} )
 end
end 
Vungle does not have Banner Ads and it will pre-load interstitial Ads itself.
iAds cannot pre-load interstitial Ads,
The codes shown above are very completed. 
You can just copy them directly and make it work.

[Corona SDK] 如何支援多個廣告系統 - AdMob, iAds, Vungle

如何加入廣告 - AdMob V2裡,
我們知道要如何加入AdMob Ads,
要加入iAdsVungle的話,作法很類似,
在這裡我們討論如果要同時支援的話該如何處理,
也就是說,我們可以動態選擇 AdMob, iAds, Vungle,
不管是因為Fill Rate, eCPM或者其它原因...

Add plugin
首先,我們需要在build.settings加入plug-in:
settings =
{
 plugins =
    {
       ["plugin.google.play.services"] =
        {
            publisherId = "com.coronalabs"
        },
        ["CoronaProvider.ads.iads"] =
        {
            publisherId = "com.coronalabs",
            supportedPlatforms = { iphone=true, ["iphone-sim"]=true },
        },
        ["CoronaProvider.ads.vungle"] =
        {
            publisherId = "com.vungle",
        },      
    },
 android =
    {

        usesPermissions =
        {
            "android.permission.INTERNET",
            "android.permission.ACCESS_NETWORK_STATE",
        },
    },
}
另外,Android需要增加網路存取的權限

Init the Ads
local adsProvider = {"adMob1","adMob2","vungle","iAds"} 
local ads = require( "ads" )
local adMobAdProvider = "admob"
local iAdsAdProvider = "iads"
local vungleAdProvider = "vungle"
local vungleAppId = "55e4xxxxxx"
local bannerAppID = "ca-app-pub-xxxxxx"
local interstitialAppID = "ca-app-pub-xxxxxx"
local appID = "com.gmail.MyCompany.App"
if ( isAndroid ) then
    bannerAppID = "ca-app-pub-xxxxx"
    interstitialAppID = "ca-app-xxxxxx"
    vungleAppId = "com.gmail.My_Company.App"
end
local lastAdsTypeShown = "none"
local currentAds = 1

local function adMobListener( event )
    local msg = event.response
    -- Quick debug message regarding the response from the library
    print( "Message from the adMob library: ", msg )
 if (event.type == "banner") then
     if ( event.isError ) then
         changeToNextAds()
     else
     end
 elseif(event.type == "interstitial") then
        if ( event.isError ) then
            changeToNextAds()
        elseif ( event.phase == "loaded" ) then
        elseif ( event.phase == "shown" ) then
        end
 end  
end

local function iAdsListener( event )
 local msg = event.response
 print("Message received from the iAds library: ", msg)
 if event.isError then
  changeToNextAds() 
 else
 end  
end

local function vungleListener( event )
   print("Message received from the vungleListener library: ", event.type)

   if ( event.type == "adStart" and event.isError ) then
     changeToNextAds()
   elseif ( event.type == "adEnd" ) then
      -- Ad was successfully shown and ended; hide the overlay so the app can resume.
   else
      print( "Received event", event.type )
   end
   return true
end

function adsInit()
 ads.init( adMobAdProvider, bannerAppID, adMobListener )
 if(isAndroid == false) then
   ads.init( iAdsAdProvider, appID, iAdsListener )    
 end
 ads.init( vungleAdProvider, vungleAppId, vungleListener )
end
我們需要針對AdMob,iAdsVungle各自呼叫ads.init()
因為callback回傳的參數不同,所以各自傳入不同callback function,
上面的程式裡,我們在callback function裡發現有錯誤時就換下一個Ads,
至於changeToNextAds()是什麼,看下一段

Change Ads Network
local function changeToNextAds()
 currentAds = currentAds + 1
 if(currentAds > 3) then
  currentAds = 1
 end
 if(adsProvider[currentAds] == "iAds") then
  ads:setCurrentProvider(iAdsAdProvider)
 elseif(adsProvider[currentAds] == "vungle") then
  ads:setCurrentProvider(vungleAdProvider)
 else
  ads:setCurrentProvider(adMobAdProvider)
 end
end
我們透過呼叫ads:setCurrentProvider()來設定新的Ads Network,

Show Ads
function showAds(type,px,py)
 if(adsProvider[currentAds] == "adMob") then
  if(type == "banner") then
   ads.show( type, { x=px, y=py, appId=bannerAppID} )
   return true
  elseif(type == "interstitial") then    
   if(ads.isLoaded(type))then
    ads.show( type, { x=px, y=py, appId=interstitialAppID } )
    return true
   else
    return false
   end 
  end 
 elseif(adsProvider[currentAds] == "vungle") then
  if (type == "interstitial" and ads.isAdAvailable() ) then
      ads.show( "interstitial" )
      return true
  else
   return false
  end   
 elseif(adsProvider[currentAds] == "iAds") then
  ads.show( type, { x=px, y=py} )
  return true
 end
 return false  
end

function loadAds()
 if(adsProvider[currentAds] == "adMob") then
  ads.load( "interstitial", { appId=interstitialAppID} )
 end
end 
Vungle沒有Banner Ads, 它自己會pre-load interstitial Ads,
iAds無法pre-load interstitial Ads,
上面的說明應該很完整,
基本上只要照抄就可以了

2015年11月16日 星期一

[Corona SDK] How to add Apple Game Center and Android Google Play Game Service

For Apple Game Center or Android Google Play Game Service, 
we just need to utilize the function of gameNetwork.
It is not difficulty to implement them.
To consider Apple and Google at the same time, 
let's check the codes first and see how them work:
local gameNetwork = require( "gameNetwork" )
local playerName
local playerId

local leaderboardsListId=
{
 ["HighestScore"]=
 {
  ["Description"] = "Highest Score",
  ["Identifier"] = "com.gmail.mycom.demo.Leaderboards.HighestScore"
 }
}

local achievementsListId = 
{
 ["FinishLevel1"]=
 {
  ["Description"] = "Finish Level 1",
  ["Identifier"] = "com.gmail.mycom.demo.Achievements.FinishLevel1"
 },
 ["FinishLevel2"]=
 {
  ["Description"] = "Finish Level 2",
  ["Identifier"] = "com.gmail.mycom.demo.Achievements.FinishLevel2"
 }
}

if(isAndroid) then
 leaderboardsListId=
 {
  ["HighestScore"]=
  {
   ["Description"] = "Highest Score",
   ["Identifier"] = "Cgkxxxxxxxx"
  }
 }

 achievementsListId = 
 {
  ["FinishLevel1"]=
  {
   ["Description"] = "Finish Level 1",
   ["Identifier"] = "Cgkxxxxxxx"
  },
  ["FinishLevel2"]=
  {
   ["Description"] = "Finish Level 2",
   ["Identifier"] = "Cgkxxxxxxxx"
  }
 }
end



function showLeaderboards( event )
 print("showLeaderboards()")
 if (playerId ~= nil) then
    if ( isAndroid ) then
       gameNetwork.show( "leaderboards" )
    else
       gameNetwork.show( "leaderboards", { leaderboard = {timeScope="AllTime"} } )
    end
 else
  gameNetworkSetup()
 end
    return true
end

local function postScoreSubmit( event )
   --whatever code you need following a score submission...
   return true
end

local function updateLeaderBoards(type, myScore)
 if (playerId == nil) then
  return
 end

 gameNetwork.request( "setHighScore",
 {
    localPlayerScore = { category=leaderboardsListId[type]["Identifier"], value=tonumber(myScore) },
    listener = postScoreSubmit
 } )
 print("gameNetwork.request( setHighScore) finished")
end

function showAchievements( event )
 print("showAchievements()")
 if (playerId ~= nil) then
    gameNetwork.show( "achievements" )
 else
  gameNetworkSetup()
 end
    return
end

local function achievementRequestCallback( event )
   
   return true
end

local function updateAchievement(type)
 if (playerId == nil) then
  return
 end
 gameNetwork.request( "unlockAchievement",
 {
    achievement = { identifier=achievementsListId[type]["Identifier"], percentComplete=100, showsCompletionBanner=true },
    listener = achievementRequestCallback
 } )
end

local function loadScoresCallback( event ) 
 if(event.data == nil) then
  print("event.data is nil")
  return
 end
 for i=1,25 do
  if(event.data[i] == nil) then
   break
  end
  print("event.data[",i,"].playerID:",event.data[i].playerID)
  print("event.data[",i,"].category:",event.data[i].category)
  if(event.data[i].playerID == playerId) then
   print("matched playID...........")
   break
  end
 end
end

local function loadLocalPlayerCallback( event ) 
 if(event.data == nil) then
  print("event.data is nil")
  return
 end

 playerId = event.data.playerID
 playerName = event.data.alias
 print("loadLocalPlayerCallback(),playerName:",playerName,",playerId:",playerId)
 if(playerId == nil) then
  return
 end
 myGameSettings.gameCerterHasEverLoggedIn = true
 saveData()   

 gameNetwork.request( "loadScores",
            {
                leaderboard =
                {
                    category = leaderboardsListId["HighestScore"]["Identifier"], 
                    playerScope = "Global",   -- Global, FriendsOnly
                    timeScope = "AllTime",    -- AllTime, Week, Today
                    --range = {1,5},
                    playerCentered = true,
                },
                listener = loadScoresCallback
            }) 
end

local function loadAchievementCallback( event )    
 if(event.data == nil) then
  print("event.data is nil")
  return
 end

 for i=1,#event.data do
  if(event.data[i] ~= nil) then
   print("event.data[",i,"].identifier:",event.data[i].identifier)
   print("event.data[",i,"].title:",event.data[i].title)
   print("event.data[",i,"].isCompleted:",event.data[i].isCompleted)
  end
 end 
end

local function gameNetworkLoginCallback( event )
 if(isAndroid==false) then
  if(event.data) then
   print("User has logged into iOS Game Center")
  else
   print("User has NOT logged into iOS Game Center")
   return 
  end
 end
 gameNetwork.request( "loadLocalPlayer", { listener=loadLocalPlayerCallback } )
 gameNetwork.request( "loadAchievements", { listener=loadAchievementCallback } )
 return true
end

local function gpgsInitCallback( event )
 if(event.data) then
  print("User has logged into Google App Play Center")
     gameNetwork.request( "login", { userInitiated=true, listener=gameNetworkLoginCallback } )
 else
  print("User has NOT logged into Google App Play Center")
 end
end

function gameNetworkSetup()
 if ( isAndroid ) then
  myGameSettings.gameCerterHasEverLoggedIn = false
  gameNetwork.init( "google", gpgsInitCallback )
 else
  gameNetwork.init( "gamecenter", gameNetworkLoginCallback )
 end
end
}
Init
In general, we can call gameNetworkSetup() in main.lua
For Android, we need to check if we have logged in successfully in gpgsInitCallback().
For iOS, we need to check if we have logged in successfully in gameNetworkLoginCallback().
The code gameNetwork.request( "loadLocalPlayer", { listener=loadLocalPlayerCallback } ) is to confirm the user who logs in.
You can go without it.
The code gameNetwork.request( "loadAchievements", { listener=loadAchievementCallback } ) is to recover the users's records.
For example, users may have ever installed this APP, remove this APP, and re-install it again.
If you think that you don't need to recover the records for them, you can go with it.

Show leaderboard
To show the leaderboard, we just need to call function showLeaderboards().
In general, we do it when user press some button

Show achievement
To show the leaderboard, we just need to call function showAchievements().
In general, we do it when user press some button.

Update leaderboard

To update leaderboard, we just need to call function updateLeaderBoards().
In general, wwe do it when user finish the game.

Update achievements 

To update leaderboard, we just need to call function updateAchievement().
In general, wwe do it when user finish some round.


Below are what differ between Apple Game Center and Android Google Play Game Service:
Apple Game Center
The data in leaderboardsListId{} and achievementsListId{}:
e.g. "com.gmail.mycom.demo.Leaderboards.HighestScore".
They are user defined, as long as they are  not duplicated.

Google Play Game Service
The data in leaderboardsListId{} and achievementsListId{}:
e.g. "Cgkxxxxxxxx".
They are defined by play store publish when you finished the setting in game center.
For Google Play Game Service, we also need to add the googlePlayGamesAppId in build.settings:
android =
    {
        usesPermissions =
        {
            "android.permission.INTERNET",
            "android.permission.ACCESS_NETWORK_STATE",
            "com.android.vending.BILLING",
        },
        googlePlayGamesAppId = "123456789012" 
    },
usesPermissions are not concerned for game service,
googlePlayGamesAppId is what you get when you link the APP in play store publish game center.